How to eliminate false success messages when implementing post-redirect-get pattern? - http

When implementing the post-redirect-get pattern in a web application, it is common for the final step in your server code to look something like this (pseudocode):
if (postSuccessful)
{
redirect("/some-page?success=true")
}
That is, the redirect URL has some kind of success parameter in the query string so that you know when to display a nice looking "Your form has been submitted!" message on your page. The problem with this is that the success=true persists in the query string when it's only needed to initialize the page. If the user refreshes the page or bookmarks it, they will receive a false success message even though no additional POST has taken place.
Is there an elegant solution to this that doesn't involve using JavaScript to eliminate success=true from both the query string and the browser history? This solution works, but definitely adds complexity to a page's load process.

You can use server side technology to implement this feature, without any JavaScript. The stes are listed below:
When post is successful, redirect to /some-page with current timestamp information:
if (postSuccessful)
{
redirect("/some-page?success=true&timestamp=1559859090747")
}
When server receives GET /some-page?success=true&timestamp=1559859090747 request, compare the timestamp parameter with the current timestamp, check whether it is within the last 3 seconds (or you can change this number according to the network environment).
If the timestamp parameter is within last 3 seconds, then it means this GET /some-page?success=true request is a result of server redirect. If not, then it's more like a result of "user refreshes the page or bookmarks it".
In server code that handling GET /some-page, render different HTML according to the result of step 3. Display the success message only when current access is a result of server redirect.

Related

Submit ASP.NET forms in parallel

I need to submit one form multiple times in parallel. The server accepts the parameter _ASYNCPOST.
I can explain in an abstract way how the page works
Login
Submit form search (POST)
POST same form with new data (all these need to be done in parallel)
In the last step, I yield all the requests with every parameter I could find (including __VIEWSTATE, EVENTTARGET, etc)
The problem is that the first post works, but the rest return an error saying "The server data does not match the browser data, hit refresh"
Is what I'm trying to achieve possible?
I followed this doc https://blog.scrapinghub.com/2016/04/20/scrapy-tips-from-the-pros-april-2016-edition/

How to reuse variables from previous request in the Paw rest client?

I need to reuse value which is generated for my previous request.
For example, at first request, I make a POST to the URL /api/products/{UUID} and get HTTP response with code 201 (Created) with an empty body.
And at second request I want to get that product by request GET /api/products/{UUID}, where UUID should be from the first request.
So, the question is how to store that UUID between requests and reuse it?
You can use the Request Sent Dynamic values https://paw.cloud/extensions?extension_type=dynamic_value&q=request+send these will get the value used last time you sent a requst for a given request.
In your case you will want to combine the URLSentValue with the RegExMatch (https://paw.cloud/extensions/RegExMatch) to first get the url as it was last sent for a request and then extract the UUID from the url.
e.g
REQUEST A)
REQUEST B)
The problem is in your first requests answer. Just dont return "[...] an empty body."
If you are talking about a REST design, you will return the UUID in the first request and the client will use it in his second call: GET /api/products/{UUID}
The basic idea behind REST is, that the server doesn't store any informations about previous requests and is "stateless".
I would also adjust your first query. In general the server should generate the UUID and return it (maybe you have reasons to break that, then please excuse me). Your server has (at least sometimes) a better random generator and you can avoid conflicts. So you would usually design it like this:
CLIENT: POST /api/products/ -> Server returns: 201 {product_id: UUID(1234...)}
Client: GET /api/products/{UUID} -> Server returns: 200 {product_detail1: ..., product_detail2: ...}
If your client "loses" the informations and you want him to be later able to get his products, you would usually implement an API endpoint like this:
Client: GET /api/products/ -> Server returns: 200 [{id:UUID(1234...), title:...}, {id:UUID(5678...),, title:...}]
Given something like this, presuming the {UUID} is your replacement "variable":
It is probably so simple it escaped you. All you need to do is create a text file, say UUID.txt:
(with sample data say "12345678U910" as text in the file)
Then all you need to do is replace the {UUID} in the URL with a dynamic token for a file. Delete the {UUID} portion, then right click in the URL line where it was and select
Add Dynamic Value -> File -> File Content :
You will get a drag-n-drop reception widget:
Either press the "Choose File..." or drop the file into the receiver widget:
Don't worry that the dynamic variable token (blue thing in URL) doesn't change yet... Then click elsewhere to let the drop receiver go away and you will have exactly what you want, a variable you can use across URLs or anywhere else for that matter (header fields, form fields, body, etc):
Paw is a great tool that goes asymptotic to awesome when you explore the dynamic value capability. The most powerful yet I have found is the regular expression parsing that can parse raw reply HTML and capture anything you want for the next request... For example, if you UUID came from some user input and was ingested into the server, then returned in a html reply, you could capture that from the reply HTML and re-inject it to the URL, or any field or even add it to the cookies using the Dynamic Value capabilities of Paw.
#chickahoona's answer touches on the more normal way of doing it, with the first request posting to an endpoint without a UUID and the server returning it. With that in place then you can use the RegExpMatch extension to extract the value from the servers's response and use it in subsequent requests.
Alternately, if you must generate the UUID on the client side, then again the RegExpMatch extension can help, simply choose the create request's url for the source and provide a regexp that will strip the UUID off the end of it, such as /([^/]+)$.
A third option I'll throw out to you, put the UUID in an environment variable and just have all of your requests reference it from there.

Is it possible to return HTTP code 200, but give a "better" url without using 3xx?

Consider StackOverflow, where each question has a unique ID, but URLs are often overridden to include a stub in the URL. For readability and other reasons the stub helps users know they are at the right place.
I have a site that returns 200 when calling a URL like:
http://stackoverflow.com/questions/28057406/
But want the URL to update to:
http://stackoverflow.com/questions/28057406/is-it-possible-to-return-http-code-200-but-give-a-better-url-without-using-3x
The first call is technically valid and the code can retrieve the object and render it perfectly fine, but I'd like to update the URL to use the stubified one.
I'd prefer to do this without a redirect as just getting the ID causes a database call to get the object. Which would mean with a redirect the process would be:
Call http://stackoverflow.com/questions/28057406/
Retrieve item 25257999 from the database to get the name to make the stub
Redirect to http://stackoverflow.com/questions/28057406/is-it-possible-to-return-http-code-200-but-give-a-better-url-without-using-3x
New HTTP Call, so retrieve item 25257999 from the database to render the final page.
If possible I'd like to not use Javascript either.
So, is it possible to return Location as part of a HTTP header with a status code of 200 and the actual page, or am I stuck using 3xx calls or Javascript?
If you are just doing HTTP, you can either choose to redirect, or not choose to redirect... You can also (with Content-Location) tell the client that the canonical address is actually somewhere else... but no browser will respond to that.
To avoid the database-call, you could of course just cache the result.
If you are in a browser however, you can dynamically update the current address without forcing a refresh, with window.history.pushState.
For more information about that call, see this other SO answer:
Modify the URL without reloading the page

Single Page Applications using ASP Web Forms

I need to implement single page applications using ASP Web Forms. I faced with a navigation problem. I need to use a navigation pattern like this:
http:// web site url / ... / page.aspx? {query string} # {ListId} / {ItemId}
When a user request a data from the server, the request on the server doesn't contain hash # (because this is a client-side feature). And it looks like this:
http:// web site url / ... / page.aspx? {query string}
So, actually I need two requests:
to get a page without hash and load javascript;
to handle hash data using javascript and async call required data from the server.
Is it possible to implement this logic with only one request?
Are there any best practices?
You can append ListId/ItemId to query string before sending request and read it regularly on a server.
var url = 'http://example.com?param1=10&param2=20#1000';
var beforeHash = url.split('#')[0];
var itemId= url.split('#')[1];
var processedUrl = beforeHash + '&itemId=' + itemId;
If your request is not already fired from JavaScript, you will have to hook into link's click event...
Or maybe you can get rid of # entirely and scroll content via JavaScript (my guess is that you use # because of local anchors to jump to different places in document)?
BTW There is window.location.hash property.
Update:
Based on your comment the flow is like this:
User types URL with #ItemId
Server returns the page
JavaScript reads #ItemId from window.location, puts it into QueryString and makes a request
Server returns the page based on modified QueryString
In this situation the two-requests pattern seems to be the only viable option. By design server does not get #Item part (called fragment). So there is no way to guess ItemId upon initial request. If after second (ajax) request, you refresh #ItemId dependant parts of the page through JavaScirpt, user experience will not be hindered much.

Redirect to Error page when user clicks the Browser Refresh button

i need to check whether the user clicking the browser Refresh button and redirect to error page. Can we do this in javascript or any server side methods in ASP.net
If you give each link you present a unique ID (e.g. a GUID) in the URL as a parameter, then you can keep track of all the requests you've processed. (You could clear out "old" requests if you don't mind the mechanism not working if someone leaves a browser open for a few days and then hitting refresh.) The first time you see a GUID, write it into the table. If you see it again, redirect to an error page.
It's pretty ugly though, and users could just edit the URL to change the GUID slightly. (You could fix this last flaw by recording the GUID when you generate it, and update the table to indicate when it's been used.)
In general, users expect to be able to refresh the page though - particularly for GET requests (even though most users wouldn't know what that means). Why do you want to do this?
Well, you can use a very famous tecnique called "Syncronizing Token" or something like that =D, mostly used to send forms.
This will work like this:
Create a function to provide a pseudo-random string token.
For every request to you page, check if a variable in Session, ex: Session["synctoken"] if present. If no, then it is the first time, generate a token and store it there.
Every link request, ex: "mypage.aspx" put a get called synctoken with another token, diferent from the one you have stored in the Session, it goes like "mypage.aspx?synctoken=2iO02-3S23d".
Then, comming back to (2), in a request, if a token is present in Session check if the GET is present (Request.QueryString["synctoken"] != null). If no, send Error. If yes check whether the Tokens (Session and GET) are different. If they are different, it is ok, store the GET into your Session (Session["synctoken"] = Request.QueryString["synctoken"]) and go to step (2). If no, then the user refreshed the page, there goes your error.
It goes like:
if (Session["synctoken"] != null) {
if (Request.QueryString["synctoken"] != null) {
if (Request.QueryString["synctoken"].ToString().Equals(Session["synctoken"].ToString())) {
// Refresh! Goto Error!
MyUtil.GotoError();
}
else {
// It is ok, store the token and go on!
Session["synctoken"] = Request.QueryString["synctoken"];
}
}
else {
MyUtil.GotoErrorPage();
}
}
else {
Session["synctoken"] = MyUtil.GenerateToken();
}
Sorry if I could not be more clear.. good luck!
You can do that, but I'm sure you shouldn't. The user is in control of the browser, and if she feels like refreshing, it your job to make sure the page refreshes. Returning an error page is the wrong answer.
you can use client side hidden variable to store a counter or you can put counter in session. Well I would suggest you to expire the page on refresh there are ways you can achieve this disable cache etc [like all banks website do].

Resources