ASP.NET page refresh event

xiaoxiao2021-03-06  100

Build your own ASP.NET page based on functional basic base classes

Release Date: 11/4/2004

| Update Date: 11/4/2004

Dino esposito

Wintellect

Scope of application:

Microsoft ASP.NET

Microsoft ASP.NET 2.0

Summary: The function can be added to the universal Microsoft ASP.NET class (for example, the PAGE class) by inheritance. This provides you with a public place so that you can add features and deploy features to all pages. In this article, Dino will show you how to add page refresh processing, support for lengthy processes, and set focus controls using the PAGE class. (This article contains links to English sites. Please note that in the sample file, the programmer's comment is in English. In this paper, it is translated into Chinese to facilitate the reader.)

Download the source code of this article.

This page

Building a more rich basic class detection browser refresh usage page refresh event enables users to get a pleasant experience in the length of operation to set the focus control conclusion

All Microsoft ASP.NET pages come from a general basic page represented by System.Web.ui.page classes. To handle requests for .aspx resources, the ASP.NET runtime will create a dynamic class and enable the class inherit the base Page class, or inherit other classes that inherit the base Page class. If you create a page in the Microsoft Visual Studio .NET 2003 project that supports the code model, dynamically created Page classes will inherit the category class, and the contents contain the code class inherit the base PAGE class.

Basic Page class implements a typical ASP.NET page lifecycle (load-return-rendering cycle), and provides a set of predefined members and features for derived pages, such as backup detection, scripting, rendering, and view status management .

All in all, System.Web.ui.page class is just a basic class, which can be used to define a set of universal, most basic features and behaviors. In a particular application, the page is likely to provide more features and provide a more powerful programming interface. There are two possible ways of extension: enhancements in the general sense of the page infrastructure, or improve features for applications. The example of the previous extension is the properties used to represent the page menu and menu items. The page for the application is typically designed based on a logical "master" page consisting of a static area, a universal area, and a customizable area. The content of these regions may vary from page, they are usually filld through templates, placeholders, and user controls.

Note that in Microsoft ASP.NET 2.0, the introduction of the master page greatly simplifies the process of creating a page using custom and programmable properties and members for applications.

However, what should I do if you need to create more functions, more complex infrastructure for the page? How to instruct all pages to provide other system level features, for example, the function of detecting the F5 (refresh) button? The code required to implement a given trick can always be combined with the operation code of each particular page (included in the code class in the coded class). However, even if two or three functions are implemented, the quality of the generated code has begun to similar to everyone spit with the Italian noodle code, which is very dangerous. You must look for other methods.

Build a richer foundation class

A better way is to create a new base Page class, use it instead of the standard system.web.ui.page class. In this article, I will introduce several common functions and their general implementation and put these functions into a new and richer Page class. The features I want to introduce include:

• Detect the F5 (refresh) button. • Start and control a lengthy operation that needs to send a feedback page to the user immediately. • Set the input focus when loading the page. If you often visit the newsgroups and community sites that specifically introduce ASP.NET, and read a lot of articles, books, and press releases, you may already know how to achieve the above functions in the ASP.NET 1.x application context. . The problem here is how to provide all of these features at the same time through a component and an entry point.

By defining a custom Page class, you can provide all other features and services on your new .aspx page on your new .aspx page and get the largest return. The declaration method created by Visual Studio .NET 2003 is as follows:

Public class Webform1: System.Web.ui.page

{

:

}

To enable web form classes to inherit non-default Page classes, simply change the base type as follows.

Public Class Webform1: msdn.page

{

:

}

If the page is not created in Visual Studio .NET 2003, you can set the fundamental type by the Inherits property in the @PAGE instruction.

<% @Page inherits = "msdn.page" ...%>

You can change the base type of the ASP.NET page as described herein, or you can use the node in the configuration file.

Let's take a look at how to implement the above functions in practical applications, and how to encapsulate these features into a unpackable class.

Back to top

Detect browser refresh

In the article on the ASPNetPro Magazine a few months ago, I summarize the steps required for this process when the user presses the F5 key refreshing the current page in the browser. The page refresh is the response of the browser to a specific user operation (pressing the F5 key or click the "Refresh" toolbar button). Page refresh operations is an operation inside the browser because the browser does not issue any external notifications for events or callbacks. Technically, the page refresh is implemented by "simple" repeating the latest request. In other words, the browser will cache the processed recent request and re-release the processed request when the user clicks on the page refresh button.

It is because all browsers (according to I know) will not provide any type of notification for page refresh events, so the server-side code (for example, ASP.NET, Typical ASP or ISAPI DLL) is simply unable to distinguish refresh requests and general submission. Or return to the request. To help ASP.NET detection and processing page refresh, you need to build an environmental mechanism that makes two exact same requests look different.

The browser implements refreshed by resending the last HTTP payload, and makes a copy looks different from the original version (this is an additional service, you need to add additional parameters and the ASP.NET page must be able to cache these parameters). The figure below provides a detailed view of the subsystem I want to build.

Figure 1: Mechanism to make refresh requests appear to be different from the return / submission request

Each request in the session context has a unique and incrementable ticket number. The ASP.NET page generates a ticket before generating a response and stores it in a custom hidden field to the browser. The hidden field (if any) will be automatically attached to the server request when the user submits a new request (thus causing the return displayed page). On the web server, the new HTTP module will intercept the AcquireSessionState event, retrieve the current ticket from the hidden field, and compare it with the ticket ID of the last processing of internal cache. (The ticket is stored last time in the session state.) If the current ticket is greater than the last processing ID, or if the two values ​​are zero, the description request is a general submission or faster. In addition, refreshing the HTTP module does not perform other operations, and the request is sent to the request.

If the ticket is greater than or equal to or equal to the current ticket, the request is identified as the page refresh. In this case, the HTTP module creates a new entry only in the Items collection of the request. In ASP.NET, the HTTPContext object represents the context of the request and always exists in the entire life cycle of the request. The Items attribute of the HTTPContext object is a collection that can be used by the HTTP module, the factory handler, and handler to forward customities to the actual page object. All the content stored in the Items collection is visible to all components involved in the process of processing the current request. The lifecycle of this information is the same as the life cycle of the requested life cycle, so all data will be destroyed once a response is generated. By using the HTTPContext.current static properties, any class involved in the process can access the currently requested HTTP context.

Refreshing the HTTP module will create a new entry named ISPAGEREFRESHED in the items collection. The Boolean value of this entry indicates that is the general submission / return request page or by refresh the request page. The following list shows the implementation of the refresh HTTP module.

Using system;

Using system.Web;

Using system.Web.SessionState;

Namespace MSDN

{

Public class refreshmodule: httpmodule {

// httpmodule :: init

Public void init (HTTPApplication APP)

{

// Register pipe event

app.acquirerequestState =

New EventHandler (onacquireRequestState);

}

// httpmodule :: Dispose

Public void dispose () {}

/ / Determine if F5 or back / forward operation is being processed

Private Void OnacquireRequestState (Object Sender, Eventargs E) {

// Access HTTP context

HTTPApplication APP = (httpapplication) Sender;

HTTPCONText CTX = app.context;

// Check F5 operation

Refreshction.check (CTX);

Return;

}

}

}

The Refreshaction class contains logic used to determine if the current request is a page refresh. If it is determined as a page refresh, a new entry will be included in the Items collection of HttpContext: ISPageRefreeshed is set to True.

Public Static void Check (HTTPContext CTX)

{

// Initialization ticket field

EnSureRefreshticket (CTX);

// Read the ticket (from the session) in the session (from a session) int lastticket = getlastrefreshticket (CTX);

// Read the currently requested ticket (from the hidden field)

INT THANTICKET = GetCurrentRefreshticket (CTX);

// Compare two tickets

IF (Thisticket> Lastticket ||

(Thisticket == lastticket && thinkicket == 0))))

{

UpdateLastRefreshticket (CTX, THisticket);

CTX.Items [PageRefreshenTry] = false;

}

Else

CTX.Items [PageRefreshenTry] = TRUE;

}

The name of the hidden field and session field is set to a common constant in the Refreshction class, and can be used outside of the class.

How do I use this mechanism? When is the test page refresh is really useful? The HTTP module does not block any request, which only adds more information to the final ASP.NET page to handle the request. The added information includes a Boolean value representing a page refresh.

Back to top

Use page refresh events

Users of the web page usually only have several operations, and to some extent, the mood is very enjoyable when performing these operations. These operations include "back", "forward", "stop" and "refresh". But these operations constitute a standard kit for an Internet browser. Intercept and subdivision These operations may bring some "limitations" to the universal recognized Internet operation. It may have a negative impact on users.

On the other hand, when the user refreshes the current page or returns to the previously accessed page, the processed request is submitted to the server, which may interrupt the consistency of the application status. In this case, it is also possible to have a negative impact on the application.

Please express the following:

You via DataGrid display data and provide a button in each row for users to delete the data lines represented. Although this is a common practice (gently click, you can delete the data implemented in the current application), but this practice is extremely dangerous. The user is easy to click the wrong button due to the mistake, and if they refresh the page after deleting (whether it is interested or unintentional), it is likely to delete the second line.

When you refresh the page, the browser only repeats the content released last time. From the perspective of the ASP.NET runtime, there is only one new request to be processed. The ASP.NET runtime cannot distinguish between general requests and unexpected repetition requests. If you take an offline work, you can delete a record in the location stored in the DataSet stored in memory, it is likely to remove a record. If the previous operation ends with INSERT, the refresh page is more likely to add a record.

These examples clearly expose certain controversial design issues, but they reflect the entire possible situation. So what is the best way to prevent the page refresh?

The mechanisms discussed above in this article can preprocess the request and determine if the page is being refreshed. This information passes to the page handler via HTTPContext objects. In the page, developers can retrieve this data using the following code.

Bool isRefresh = (BOOL) httpContext.current.items ["ispagerefreeshed"];

But a better approach is that if you use custom, more targeted Page classes, you can package data into a more easy to use, that is, encapsulate into the ISPageRefresh property.

Public bool ispagerefresh {

Get {

Object o = httpContext.current.Items [refreshction.pagerefreshenTry];

IF (o == NULL)

Return False;

Return (BOOL) O;

}

}

By enabling the PAGE class to inherit new, a richer basic class (this example is MSDN.Page), you can understand the real cause of the request. The following example shows how to implement some key operations that should not be repeated when the page is refreshed.

Void AddContactButton_Click (Object Sender, Eventargs E) {

IF (! ispagerefresh)

AddContact (FName.Text, Lname.Text);

Binddata ();

TrackRefreshState ();

}

Add a new contact only if you don't refresh the page, in other words, you will add contact only when the user clicks on the "Add-Contact" button according to the regular manner. There is a very strange TrackRefreshState method in the above code snippet. What is its role?

This method updates the ticket counter and make sure the new page response contains hidden fields with the latest ticket. In this example, the next ticket is obtained by increasing the value stored in the session state. (Here is just a session state, it is best not to use a session state, and use a more scalable provider model, just like in ASP.NET 2.0.)

However, about the TrackRefreshState method (this is intentional, so that everyone thinks about the more familiar TrackViewState method), there is a point to explain. By calling this method, in addition to adding additional information, you can also add a hidden field with the current request ticket to the page response. If there is no hidden field (see Figure 1), the refresh mechanism will not be able to detect that the next flexion is refreshed or submitted. In other words, by calling TRACKREFRESTATATE in the rapid event handler, the system knows that you want to track the operation (and only track the operation) to determine if it is refreshed for the page. This way, you only track the page that may be wrong, and not all pages are refreshed during the session life cycle.

To use the page refresh feature, simply add a new page in the Microsoft Visual Studio .NET project, then open the encoded code file and change the base class of the page to msdn.page. Next, call the TrackRefreshState (new public approach) of the MSDN.Page class when you perform an operation that should not be refreshed. Check the refresh status using the new Boolean properties ISPAGEREFRESH.

Back to top

User users get a pleasant experience during lengthy operation

With regard to how to track special time-consuming operations on the Web, you have provided a variety of solutions through multiple articles and many speeches. What I said "time-consuming operation" refers to all operations that usually require the progress bar in a Windows form scheme. It is easy to show the progress bar on the web page. The progress bar should be able to communicate with the server to obtain information that helps update progress. In addition, this operation should not be completed by flexing or refreshing the metallic tag to avoid completely refresh the page. In any case, powerful dynamic HTML support is required.

To enable users to get a pleasant experience during the length of operation, relatively simple method is to display an intermediate feedback page, showing some waiting messages for the user, preferably with a point animation. This page is completely unrelated to the context, but it is undoubtedly more useful to display an hourglass over a blank page before the new page is loaded.

To display some feedback during length, there is a simple and efficient method, which can be summarized as follows: • Once the user reacts the user to the feedback page once the user begins to start the task. The feedback page must know the URL of the page actually performing the task. This URL (including session state) can be passed by querying a string or placed in accessible data storage. • After starting the feedback page, redirect to the work page. In this case, the redirect is done by the script in the online ONLOAD JAVAScript event. The browser loads and displays the feedback page and then points to the work page. The page starts performing lengthy tasks while displays the feedback page for the user. • The feedback page can be complex and include many UI elements as needed. It can contain "Please wait ..." message or display animation GIF, or with some dynamic HTML features, display some seem to be a true progress bar.

I deliberately created a LengthyAction class to help manage the beginning of lengthy tasks.

Private const string urlformatstring = "{0}? target = {1}";

Public Static Void Start (String FeedBackPageurl,

String TargetPageurl)

{

// Prepare the URL of the feedback page

String Url = String.Format (urlformatstring,

FeedbackPageURL, TargetPageURL;

// Redirection to the feedback page

HttpContext.current.response.redirect (URL);

}

The feature of this class is that there is only one static method, that is, START. The START method obtains the URL of the feedback page and the target page (ie, the page that performs tasks). This method combines two parameters into a URL and redirects.

The feedback page can contain any user interface you want, but you must meet several key requirements. This page must be able to retrieve the name of the work page and provide a possible automatic mechanism to redirect to the work page via the script. I define a custom base Page class and built into these features in this class. When doing this, I have to make some assumptions. In particular, my implementation assumes that the name of the work page is passed by the query string using you well-known attribute name Target. The name of the target page is stored in the public property named TargetURL. In addition, the feedback page provides a function called GetAutoredirectScript. The purpose of this function is to return the script code that is redirected by the script implementation.

Public String getAutoredirectScript () {

Return string.format ("location.href = '{0}';", TargetURL);

}

In order to make the problem as simple as possible, the FeedbackBasePage class also finds a general HTML control called Body. This is exactly the same as you get in the following tags.

If you can program the text of the page via a simple method, the FeedbackBasePage class will find this method and automatically add an OnLoad property; otherwise, you must manually add an OnLoad property. To make the feedback page work properly, this property is required.

HtmlGenericControl body = findcontrol (bodyid) AS HTMLGENERICCONTROL

IF (body! = null)

Body.attributes ["OnLoad"] = getAutoredirectScript (); finally provided to the browser's tag code as shown below.

Let us see which steps need to perform using the length of the class discussed herein.

First refer to the desired assembly, then write the following event handler for the click button of the trigger operation.

Void ButtonLengthyop_Click (Object Sender, Eventargs E) {

Lengththyaction.start ("feedback.aspx", "work.aspx");

}

Next, add a feedback page in the project. This is a regular Web form page that you can modify its tag as described above, and change the underlying class to FeedbackBasePage. The user interface of the feedback page will be displayed after you click the button start process and the result is displayed, as shown in the following figure.

Figure 2: Sequence of lengthy operation

In this example, I used a transmital return, which is a more common plan for special lengthy operations. However, this has triggered the issue of passing the view status and the work page to complete its task usually required. You can use the query string of the work page to connect the serialized object version, or store all the content in the ASP.NET cache or session object. In this case, the HTTP context cannot be used because the operation involves multiple HTTP requests, and each request has a different project set.

Note that the URL of the feedback page contains some details of the call and may be as follows.

Feedback.aspx? target = work.aspx? param1 = 123 & param2 = Hello

To hide these details, you can define a custom HTTP handler and bind them to the virtual URL you think more suitable. The HTTP handler can retrieve the required information from the cache or session state (including the name of the feedback page and the work page).

Back to top

Set focus control

ASP.NET 2.0 provides a very good new feature that allows you to specify which input control settings set to focus when the page is first displayed. This is a flexible feature that reduces the burden on the user by clicking the start operation, for example, click Start Enter data in the text box.

To specify an HTML component as an input focus, you need a small JavaScript code. First, state it: This is not a sharp rocket science, you can easily add this JavaScript code as an inline code to the ONLOAD property of the tag. However, the name of the focus control on the server is used to determine the name of the focus control on the server. It is really a big step. In fact, you can use the following code in ASP.NET 2.0.

Void Page_Load (Object Sender, System.EventArgs E) {

SetFocus ("Thefirstname");

}

When the page is displayed, the input control named thefirstname will become a focus. This method is convenient, but how do I encode it in ASP.NET 1.x?

Similarly, the skills that implement this function have been well known for industry people, or can search for effortlessness from Google. But the problem is how to integrate it into the base Page class for reuse.

Let us use the following statements to extend the MSDN.Page fundamental class.

Private string m_focusedControl;

Public void setfocus (string ctlid) {m_focusedControl = CTLID;

}

The SetFocus method collects the ID of the control and stores it in an internal member. In the prerender event in the page, call another help program to build and insert JavaScript code.

Private void addsetfocusScript ()

{

IF (m_focusedcontrol == "")

Return;

// Add script to declare function

StringBuilder SB = New StringBuilder ("");

Sb.append ("