I work on ASP.NET C#. Under button click event I want to save something it's work fine, but after press the refresh button of browser, this event occurs again I want to stop this event.
An article on this subject.
Preventing Duplicate Record Insertion on Page Refresh
Approach 1
A simple solution is to
Response.Redirect back to the same
page after the INSERT command is
called. This will call up the page
without transmitting any post headers
to it. Using Request.Url.ToString()
as the first parameter of
Response.Redirect will cause both the
URL and the page's querystring to be
included in the redirect. The use of
false as the second parameter will
suppress the automatic Response.End
that may otherwise generate a
ThreadAbortedException. A
disadvantage of this approach is that
any ViewState that had been built up
will be lost.
Approach 2
A related approach would be for the form to submit to an intermediate processing page and then Response.Redirect back to the calling page, similar to the classic ASP approach to form processing. This has the same effect as simply using the Response.Redirect in the Button_Click event so it has the same disadvantages, with the added disadvantage of creating another page for the website developer to manage.
Approach 3
The next batch of solutions works by
determining whether the user has
refreshed the page in the browser
instead of pressing the form's submit
button. All of these solutions depend
on the ability of the website to use
Session variables successfully. If
the website uses cookie-based
Sessions, but the user's browser does
not permit the use of cookies, these
solutions would all fail.
Additionally, should the Session
expire these solutions would also
fail.
Approach 4
Should the user somehow manage to
circumvent the above mentioned solutions described
above, the last line of defense is at
the database. There are two methods
that can be employed to prevent a
duplicate record from being inserted
into the database. For each method,
I've moved the SQL code into a stored
procedure, since there are now more
processing steps involved and these
are easier to illustrate in a separate
stored procedure. Note however that a
stored procedure is not strictly
required in order for these methods to
work.
Related
I have a performance issue where we have a 2 page setup as part of a workflow in a bigger system. This section is dedicated to rendering reports allowing users to chose their own parameters.
Page1.aspx collects parameter information for a report. It takes the information submitted on a form and validates it. If it validates OK, it stores the selections in the DB as XML, then redirects to Page2.aspx with the run id in the query string. Simple enough, performance is great.
Page2.aspx pulls the ID out of the DB and hydrates a Crystal ReportDocument object (taking milliseconds) then we call ExportToHttpStream which then renders the report as a PDF or DOC or XLS download (output format is determined in Page1.aspx). The performance of the ExportToHttpStream method is very poor due to the way our reports are written and DB indexes on the target system. This is outwith my control at the moment but I am promised that they are being worked on.
So the problem is, that when the submit button in Page1.aspx is pressed, the user experiences a very long delay before the download starts. It is then compounded by the user pressing the submit button again thinking there is a problem.
I think what I need to do is have Page1.aspx redirect to Page2.aspx. Page2.aspx should render the master page furniture and a loading div, and the report should render asynchronously somehow in the background before the save dialogue automatically pops up, after this i'd like to change the loading div to a 'Report generated, click here to go back'.
If this is the best way to achieve this, how can I load a full page, then request the report asynchronously? I'm open to any suggestions here.
You could use ajax to load the report on Page2.aspx and show a loading message while it's processing.
Look at the jQuery.load() method. This might be the easiest way to accomplish what you are trying to do.
Page1.aspx - collect parameters
Page2.aspx - report view, calls Page2Details.aspx via ajax.
Try loading Page2.aspx inside iframe and use jQuery to display waiting indicator and hide it after Page2.aspx download
Whilst both answers gave me some ground to go out and research in the right direction. My solution included using the fileDownload plugin from John Culviner to facilitate a similar solution:
jQuery fileDownload by John Culviner
This allowed me the following page structure:
Page1.aspx, gathers and validates parameters for the report and puts them into Oracle.
Page2.aspx, whilst passed in the runid (pointer to the parameters in the db) via the query string setup 3 hidden divs. Loading, Error and Success.
The script mentioned above was employed at this point. jQuery firstly sets the loading div visible then calls the plugin. The plugin dynamically creates an iframe and downloads the binary (xls/doc/pdf) from Page3.aspx. It then fires a success callback or failure. The success callback is fired by means of a cookie set at the end of the response in Page3.aspx.
I believe the plugin mentioned downloads using a 'text/plain' AJAX call in jQuery avoiding the limitation of there not being an octet-stream equivalent in AJAX.
It works, its not the cleanest solution by any means, it doesn't degrade one bit, but provides the users on our controlled intranet with an extremely responsive and pleasing UI.
It is possible to have a control that would proxy requests to another domain/Web site, including postback?
In this control, you would specify the URL you wanted to execute, and whenever the control executed, it would make a GET request to this other URL, and render the HTML return. (This part is not hard.)
However, when the page is posting back, it would make a POST request, with all of its postback variables intact, to this other page.
I'm really looking for a blind proxy. Some control that will take the incoming request and throw it another URL, and render the results. The other page would really have no idea it wasn't interacting with a human.
I want to think I could develop this, but I can't be the first person who wants to do it, so there has to be some reason why Google isn't revealing the solution to me. I suspect I'm going to run into the same Big Problem that anyone else with this idea has run into.
I'm not exactly sure what the value of this is; which is probably why you haven't found a solution yet.
However, it seems to me that there are two possible solutions.
When the page is rendered have the control modify the form action to point elsewhere; or,
on post back, have the control execute a web request to the alternate URL with the post variables and decide what to do with the results at that time.
In this end, this never had much of a chance of working. I experimented with it for a while, but Postback requires intimate knowledge of the control tree, and there's no way that you're going to be able to apply a postback from the calling page to the other page and have it overlay correctly because the control trees between the two pages are totally different.
Now, if you wanted to write the backend app as a more traditional Web app (even something not in ASP.Net), it might work. During postback, you could iterate the Request.Form values and send them back, and just have your backend app prepared to accept those incoming values and deal with them, but this wouldn't be a traditional postback.
I have a wizard style interface where I need to collect data from users. I've been asked by my managers that the information is to be collected in a step by step type process.
I've decided to have a page.aspx with each step of the process as a separate user control. step1.ascx step2.ascx etc...
The way it works now, is that when the initial GET request comes in, I render the entire page (which sits inside of a master page) and step1.ascx. When then next POST request comes in for step 2 (using query string step=2), I render only step2.ascx to the browser by overriding the Render(HtmlTextWriter) method and use jQuery html() method to replace the contents of a div.
The problem with this whole approach, besides being hacky (in my opinion) is that it's impossible to update viewstate as this is usually handled server side.
My workaround is to store the contents of step1.ascx into temporary session storage so if the user decides to click the Back button to go back one step, I can spit out the values that were stored for it previously.
I feel I'm putting on my techy hat on here in wanting to try the latest Javascript craze as jQuery with .NET has taken a lot of hack like approaches and reverse engineering to get right. Would it be easier to simply use an updatepanel and be done with it or is there a site with a comprehensive resource of using jQuery to do everything in ASP.NET?
Thanks for taking the time to read this.
Another approach, that might be easier to work with, is to load the entire form with the initial GET request, and then hide all sections except the first one. You then use jQuery to hide and show different parts of the form, and when the final section is shown the entire form is posted in one POST to the server. That way you can handle the input on the server just as if the data entry was done in one step by the user, and still get the step-by-step expreience on the client side.
You could just place all your user controls one after another and turn on the visibility of the current step's control and turn on other controls when appropriate . No need to mess with overriding Render(). This way the user controls' viewstate will be managed by the server. and you can focus on any step validation logic.
Using an UpdatePanel to contain the steps would give the ajax experience and still be able to provide validation on each step. If you are OK with validating multiple steps at once, Tomas Lycken's suggestion (hide/show with JQuery), would give a fast step by step experience.
Did you look into using the ASP.NET Wizard control? It's a bit of a challenge to customize the UI, but otherwise it's worked well for me in similar scenarios.
I want to redirect the user to another page to fill out a captcha but i would like to keep the post data, and if the captcha pass to send it 'back' and complete the previous page action.
When/if the user succeeds i like to add an captchaPass=true and would like access the post data and continue processing. Right now i am using redirects but ATM i am not required to use it.
Is it possible to carry the post data? keep in mind i may the user access multiple pages so separating data and not having a mixup is necessary.
One idea is to get and save all posted data [1] on the captcha page, and then recreate a middle white page with this form data and automatically make a new post to the previous page.
Can this work with out any issues with hash checks and security ?
Is there a better idea with out this white redirect page ?
[1] One other issue here, how to send this posted data with the redirect ? and not change the url - or make it too big to accept it. Keep in mine that a server transfer may not good idea because is complicate the thinks on captach post back.
Update 1
The basic idea here is how some one capture the full post back of a page, show a different one page and then send the post back data to the original first one.
The reason is to stop a bad user, or an attacker bot program that try to bring down the pages/server by making many post back from different pages in short time. All that happens with out javascript, and most attackers use custom made programs that just make post of data to all page together try to bring down the system.
For example, if a page have a search box, is very easy for most of the the site to bring them down by start making hundred of random search with wildcard (called and Dos Attacks using SQL wildcards) and make the sql server and the computer spend his time and cpu to search and search thinks. So to prevent an attack like this you need to recognize multiple post backs from the same computer, and then the next step is to redirect him to a captcha page to block him out in case that is a computer program.
Other example, many page have email submit, very easy you can submit hundred times the email of his and full his mail box in no time with hundred of emails, or on a store to place all items on the cart again and again and full the database with stuff like that.
So ajax and javascript is not working in this case, and we need a way to redirect him after the post back to a page that can check if is a real user or an attacker and stop him - but if is a real user must return back to his normal action.
Update 2
This all must be done in a general way, eg on BasePage, or on Global.asax or somewhere that is independed from the content of any page. Because we try to prevent a DoS attack, or multiple submit anywhere on any random place of any random page.
Yes I know how you can place a captcha on the contact page, but this is not what this question was first asked for - this questions asked how can carry post data to one different page, keep them there and then resend them back to the original one.
The obvious solution is to read all post back, and save them on the form, and then read them back and make on fly a form only with that data and make the post back. Here I am asking if there are any other better than this solution.
Other Applications
There is also the case that a user is inside a page that request authentication, but the authentication ticket has expired, and the user make post back. In this case we need to keep somewhere all the posted back data, to proceed with the login page, and resend them back to the first page that request the authentication.
Sure, just write the form data out to the captcha page in hidden elements with the additional captcha fields added to the form. Have your submit action post the whole thing back to the original. Using ASP.NET it's probably easier to have the captcha written to the same page with the form fields hidden, but you can do cross-page postbacks as I've described above.
Cross Page Posting might help you.
Why not implement the CAPTCHA with AJAX? Load the captcha object and form with Javascript in a div perhaps displayed lightbox style, accept the user input and post it to your server for validation, hence continue with the users post request or keep them there until they get it right (or cancel).
A more specific situation example:
Give the form submittal button an onClientClick value of some Javascript function. This function decides if this particular form needs a CAPTCHA. If it does it loads an interface for taking the CAPTCHA (which you'd need to do with some server-side code) and inserts the CAPTCHA's input element to the form that the user clicked to submit.
Once the user has entered the CAPTCHA input and clicks some button whose click event is bound to return to your first JS function, the Javascript intercepts this action and posts the full form, all the data from the original form and the CAPTCHA for validation. Your server script can now process all this at once!
This is the best solution I can think of that works similar to how you've asked, but I can't imagine why you want to perform the CAPTCHA on a different page.
Server.Transfer with MultiViews, Panels like control is fine with you? In this way, no need to bother about the Data Maintenance and Postbacks. You can do the validations in javascript.
You can keep both functionality in the same page to avoid moving data from one page to another page/Bring the data back to original page. You can utilize Session for this intermediate operation. Set it back to associated controls across Postback. You can create a class, Instantiate it and Initialize the control values in this class object. Save class object in Session. On Postback, You can reassign the values to the associated controls. This will definitely keep the things simple and without much complexity.
Doubts ?
I am using VS 2005, C# 2, ASP.Net 2.0
I am unable to find out how to track that user pressed F5/Ctrl+F5/ Open a new Window(Ctrl + N) in ASP.Net.
I know that there is a Page.IsPostBack property, which tells that a page is loaded in response to an action taken by user.
I am just curious to know, that why isn't there a property as IsRefresh or Page.IsRefresh in ASP.Net, which will return true,
whenever user takes any of the above actions.
Is there a way to know this?
Actually my problem is that i have a DLL using which all of my aspx pages are inherited, I have to
insert some values in a table whenever the page is opened for the first time that's it, if user just opens the page or do not take any action,
an entry should be inserted into the database, but as far as I have tried, I controlled it anyhow using the Page.IsPostBack property, but I got stuck
in the refresh case, as it is inserting records unconditionally.
Similar to using a function in Global.asax (as others have suggested) you could use a session variable "flag". When the page first loads set a session variable and then just check against it in your page load function:
if (Session("visited") != "true"
//page has not been visited, log visit to DB
Just make sure you set the session flag sometime after the above check during the page load.
It won't be exact (sessions can timeout while a page is active, users can completely leave the site and come back in the same browser and the session stays alive, etc) but for your tracking it is much better than counting every page hit in the DB.
Perhaps you want the Session_Start method in the Global.asax file, which will be triggered once at the start of each user session?
In your Global.asax file, add or edit the method:
void Session_Start(object sender, EventArgs e)
{
}
why isn't there a property as IsRefresh or Page.IsRefresh in ASP.Net
Because ASP.NET cannot possibly know. The browser does not send any information that could allow it to determine whether the page is being requested due to a refresh or normal load. You will need to reconsider your requirements: what is the actual purpose of the database logging?
Session_Start method in Global.asax file is fired every time when a browser session is started. You can use this method to count number of unique users on your website.
Session_End method in Global.asax is fired when a session ends (explicitly or timedout). So you can decrement the count here.
Hope the above to example uses of these methods helps you understand how you can use them.
Because of the stateless nature of HTTP protocol there is no way to tell apart the initial load from the refresh
As has already been said. This isn't possible. A request issued due to a refresh is no different to a request issued the first time the page is loaded.
It sounds to me like you are trying to track page views somehow. This is certainly possible though it will require some work on your part. Your best bet is probably to log the URL of the page. You may also want to include the query string in order to differentiate between page loads for different pieces of data (if this happens in your application). You will also want to log the ID of the current user, and the ID of their session.
You can then make sure that you don't insert two page views for the same user for the same page in the same session, effectively filtering out any reloads of a page.
You do need to be aware that this isn't the same as detecting a refresh, what you are detecting is two page views in the same session, this could be a refresh, or it could be use of the back button, or just reloading from the address bar.
My suggestion would be to create a cookie on very first load, then on Page_Load check to see if the cookie exists. If it does, don't insert the record. You can use Session_End to destroy or create the cookie as someone suggested if that works with your application's architecture.