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

Source: Internet
Author: User
Tags blank page

Abstract:You can add a function in a common Microsoft ASP. NET class (such as a page class) through inheritance. This provides a public place for you to add features and deploy them on all pages. In this article, Dino will show you how to add page refresh processing, support for lengthy processes, and use the page class to set focus controls. (This article contains links to English sites. Note that in the example file, the comments of programmers are in English. In this document, the comments are translated into Chinese to facilitate your understanding .)

Download the source code of this article.

All Microsoft ASP. NET pages are free of chargeSystem. Web. UI. PageGeneric basic page. To process requests for. aspx resources, the ASP. NET Runtime Library creates a dynamic class that inherits the basicPageClass, or inherit other classes that, in turn, inherit the basic page class. If you create a page in a Microsoft Visual Studio. NET 2003 project that supports code modelsPageClass will inherit the embedded code class, and the embedded code class will inherit the basic page class in turn.

BasicPageClass implementation typical ASP. NET page lifecycle (load-re-send-rendering cycle), and provide a set of predefined members and functions for derived pages, such, sending Back detection, script insertion, rendering, and view status management.

All in all,System. Web. UI. PageA class is just a basic class that can be used to define a group of common and basic functions and behaviors. In a specific application, the page is likely to target more functions and provide more powerful programming interfaces. There are two possible ways to expand: To enhance the page infrastructure in the general sense, or to improve functions for applications. The previous extension example is used to indicate the properties of page menus and menu items. Pages for applications are generally designed based on the Logical "master" Page consisting of static areas, common areas, And customizable areas. The content of these areas may vary with pages, which are typically filled with templates, placeholders, and user controls.

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

However, what if you need to create a richer and more complex basic structure for the page? How to instruct all pages to provide other system-level functions, such as detecting the F5 (refresh) key function? The Code required to implement a given skill can always be combined with the operation code of each specific page (included in the Code class. However, even if only two or three functions are implemented, the quality of the generated code has begun to be similar to the pasta-style code, which is very dangerous. You must look for other methods.

Build basic classes with richer Functions

A better way is to create a new basic page class, which replaces the standard system. Web. UI. Page class. In this article, I will introduce several common functions and their general implementations, and load these functions into a new page class with richer functions. The features I want to introduce include:

  • Detects the F5 (refresh) Key.

  • Start and control a lengthy operation that needs to immediately send feedback pages to users.

  • Set the input focus when loading the page.

If you are familiar with ASP. net news groups and community sites, and read a large number of articles, books and press releases, you may already know how.. Net 1.x application implements the above functions in the context. The question here is how to provide all these features at the same time through a component and an entry point.

By defining a custom page class, you can provide all other functions and services on the new. ASPX page with minimal effort and get the maximum return. The Declaration of the included code page created using Visual Studio. NET 2003 is as follows:

public class WebForm1 :System.Web.UI.Page{:}

To make the web form class inherit a non-default page class, you only need to change the basic type as follows.

public class WebForm1 :Msdn.Page{:}

If the page is not created in Visual Studio. NET 2003 or embedded code is used, you can use@ PageIn the commandInheritsThe property sets the basic type for the page.

<% @Page Inherits="Msdn.Page" ... %>

You can change the basic type of the ASP. NET page one by one as described here, or you can use<Pages>Node.

<pages pageBaseType="Msdn.Page" />

<Pages> NodePagebasetypeAttribute indicates the name and assembly of the class to be used as the basic type of all dynamically created page classes. By default, this attribute is setSystem. Web. UI. Page. You can overwrite the setting in the web. config file of the application.

Next let's take a look at how to implement the above functions in practical applications, and how to encapsulate these functions into a class that is all-encompassing.

Detect browser refresh

This section describes the steps required to detect the process when you press F5 in the browser to refresh the current page. Page refresh is the browser's response to specific user operations (Press F5 or click "refresh" toolbar button. Page refresh is an internal operation of the browser, because the browser does not send any external notifications for events or callbacks. Technically, page refresh is implemented by repeating the latest request in a "simple" way. In other words, the browser caches the latest processed requests and resends the processed requests when the user clicks the page refresh key.

It is precisely because all browsers (as far as I know) do not provide any types of notifications for page refresh events, so the server-side code (such as ASP. NET, typical ASP, or ISAPI DLL) cannot be differentiated at all.RefreshRequests and GeneralSubmitOrResendRequest. To help ASP. NET detect and process page refreshes, you need to build an environment mechanism that makes two identical requests look different.

The browser refresh by resending the HTTP payload sent last time and make the copy look different from the original version (this is an additional service and requires additional parameters and ASP.. NET page must be able to cache these parameters ). Provides a detailed view of the subsystem I want to build.


Figure 1 :The Mechanism set to make the refresh request look different from the sending/submitting request

Each request processed in the Session Context obtains a unique and incremental ticket number. The ASP. NET page generates a ticket before a response is generated, and stores it in a custom hidden field and sends it to the browser. When a user submits a new request, which leads to the display of the page, the hidden field (if any) is automatically attached to the server request.

On the web server, the new HTTP module interceptsAcquiresessionstateEvent to retrieve the current ticket from the hidden field and compare it with the last ticket ID processed in the internal cache. (Tickets processed last time are stored in the session state .) If the current ticket is greater than the ID processed last time, or if both values are zero, the request is generally submitted or resent. In addition, the HTTP refresh module does not perform any other operations and sends requests intact.

If the last processed ticket is greater than or equal to the current ticket, the request is marked as a page refresh. In this case, the HTTP module onlyItemsCreate a new entry in the set. In ASP. NET,HttpcontextObject indicates the request context, which always exists throughout the request lifecycle.HttpcontextThe items attribute of an object is a set that can be used by the HTTP module, factory handler, and handler to forward custom information to the actual page object. All content stored in the items collection can be seen for all components involved in the process of processing the current request. The lifecycle of the information is the same as that of the request. Therefore, once a response is generated, all data is destroyed. UseHttpcontext. CurrentStatic attribute. You can access the HTTP context of the current request from any class involved in this process.

Refresh the HTTP ModuleItemsCreate a collection namedIspagerefreshed. The Boolean value indicates whether the request page is refreshed through normal submission/sending back request pages. The following list shows the implementation of the HTTP refresh module.

using System;
using System.Web;
using System.Web.SessionState;
namespace Msdn
{
public class RefreshModule: IHttpModule {
// IHttpModule :: Init
public void Init (HttpApplication app)
{
// Register pipeline events
app.AcquireRequestState + =
new EventHandler (OnAcquireRequestState);
}
// IHttpModule :: Dispose
public void Dispose () {}
// determine if F5 or back / forward operations are being processed
private void OnAcquireRequestState (object sender, EventArgs e) {
// access the HTTP context
HttpApplication app = (HttpApplication) sender;
HttpContext ctx = app.Context;
// check F5 operation
RefreshAction.Check (ctx);
return;
}
}
}

RefreshactionClass contains the logic used to determine whether the current request is a page refresh. If the page is determined to be refreshed,HttpcontextOfItemsThe set contains a new entry:IspagerefreshedSetTrue.

public static void Check (HttpContext ctx)
{
// Initialize ticket fields
EnsureRefreshTicket (ctx);
// read the last ticket processed in the session (from the session)
int lastTicket = GetLastRefreshTicket (ctx);
// read the currently requested ticket (from the hidden field)
int thisTicket = GetCurrentRefreshTicket (ctx);
// compare two tickets
if (thisTicket> lastTicket ||
(thisTicket == lastTicket && thisTicket == 0))
{
UpdateLastRefreshTicket (ctx, thisTicket);
ctx.Items [PageRefreshEntry] = false;
}
else
ctx.Items [PageRefreshEntry] = true;
}

The name of the hidden field and session field isRefreshactionClass is set as a public constant and can be used outside the class.

How can an application page use this mechanism? When is page refresh really useful? The HTTP module does not block any requests. It only adds more information to the final ASP. NET page to process requests. The added information includes a Boolean value indicating page refresh.

Use Page refresh events

Web page users usually only perform a few operations, and to some extent, they are very happy to execute these operations. These operations include "back", "forward", "stop", and "refresh ". However, these operations constitute a standard toolkit for Internet browsers. Intercepting and segmenting these operations may bring some "limitations" to Internet operations that are generally recognized ". It may have a negative impact on users.

On the other hand, when you refresh the current page or return to the previously accessed page, the user will submit the processed requests to the server, which may interrupt the consistency of the application status. In this case, it may also have a negative impact on the application.

Consider the following:

You passDataGridDisplay data and provide a button in each row for you to delete the data row. Although this is a common practice (click to delete the data implemented in the current application), it is extremely dangerous. It is easy for users to click the wrong button due to a mistake, which breaks down data consistency. If they refresh the page after deleting (intentionally or unintentionally, the second row is likely to be deleted.

When you refresh the page, the browser only repeats the last published content. From the perspective of ASP. NET Runtime Library, there is only one new request to be processed. The ASP. NET Runtime Library cannot distinguish between common requests and unexpected duplicate requests. If you use the offline mode andDatasetTo delete one more record. If the last operation ends with insert, refresh the page and you may add a record.

These examples clearly expose some controversial design issues, but they reflect the full potential. So what is the best way to prevent page refreshing?

The Mechanism discussed earlier in this article can pre-process requests and determine whether the page is being refreshed. The information passes throughHttpcontextThe object is passed to the page handler. On the page, developers can use the following code to retrieve the data.

bool isRefresh = (bool) HttpContext.Current.Items["IsPageRefreshed"];

However, a better way is to use custom, more targetedPageClass, You can encapsulate data into a more easy-to-use attribute, that is, encapsulatedIspagerefreshAttribute.

public bool IsPageRefresh {
get {
object o =
HttpContext.Current.Items[RefreshAction.PageRefreshEntry];
if (o == null)
return false;
return (bool) o;
}
}

EnablingPageClass inherits the new and more functional basic classes (msdn. page in this example). You can learn the real cause of the request through the new attributes. The following example shows how to implement a key operation that should not be repeated during page refresh.

void AddContactButton_Click(object sender, EventArgs e) {
if (!IsPageRefresh)
AddContact(FName.Text, LName.Text);
BindData();
TrackRefreshState();
}

Add a new contact only when the page is not refreshed. In other words, only when the user clicks"Add-Contact"(Add contact) button to add a contact. There is a strangeTrackrefreshstateMethod. What is its function?

This method updates the ticket counter and ensures that 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. (The session state is used at will. It is best not to use the session state, but to use a more scalable Provider Model, just like in ASP. NET 2.0 .)

HoweverTrackrefreshstateMethod (this is intentionally named, so that you can recall the more familiarTrackviewstateMethod. By calling this method, in addition to adding other information, you can also add hidden fields with the current request ticket to the page response. If no field is hidden (see figure 1), the refresh mechanism cannot detect whether the next sending request is refreshed or submitted. In other words, by callingTrackrefreshstateSo that the system knows that you want to track this operation (and only trace this operation) to determine whether the page is refreshed. In this way, you only track page refreshes that may cause errors, and not all page refreshes will occur within the session lifecycle.

To use the page refresh function, you only need to add a new page in the Microsoft Visual Studio. NET project, open the code file, and change the basic class of the page to msdn. Page. Next, callTrackrefreshstate(The New Public method of the msdn. Page class ). Use the new Boolean attributeIspagerefreshCheck the refresh status.

Provides a pleasant experience during lengthy operations.

I have provided you with various solutions through many articles and Multiple presentations on how to track time-consuming operations on the web. What I call "time-consuming operations" refers to all the operations in the progress bar in the Windows Forms solution. The progress bar displayed on the web page is prone to problems. The progress bar should be able to communicate with the server to obtain information that helps update the progress. In addition, this operation should not be completed by sending back or refreshing the metatag to avoid completely refreshing the page. In any situation, powerful dynamic HTML support is required.

To give users a pleasant experience during lengthy operations, a relatively simple method is to display an intermediate feedback page to show users some waiting messages, preferably with a dot animation. This page is completely irrelevant to the context, but it is undoubtedly more useful than displaying an hourglass on a blank page for a long time before loading a new page.

There is a simple and effective way to display some feedback during lengthy operations. It can be summarized into the following steps:

  • Once you click to start the task, the user is redirected to the feedback page. The feedback page must know the URL of the page where the task is actually executed. This URL (including session Status) can be transmitted through query strings or stored in accessible data storage.

  • After loading the feedback page, redirect to the work page. In this case, redirection is completed by scripts in the onload JavaScript event of the page. The browser loads and displays the feedback page, and points to the work page. The page starts executing lengthy tasks and displays the feedback page for users.

  • As needed, the feedback page can be complex and contain many UI elements. It can contain a "please wait..." message or animated GIF, or use some dynamic HTML functions to display something that looks like a real progress bar.

I createdLengthyactionClass to help manage the beginning of a lengthy task.

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);
// redirect the call to the feedback page
HttpContext.Current.Response.Redirect (url);
}

This class features only one static method, that isStart.StartObtain the URL of the feedback page and target page (that is, the page for executing the task. This method combines two parameters into a URL and redirects them.

The feedback page can contain any user interface you want, but 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 through scripts. I have defined a custom basis.PageAnd add these functions to the class. In doing so, I must make some assumptions. In particular, my implementation assumes that the name of the work page uses a well-known attribute name.TargetIt is passed through the query string. The name of the target page is stored inTargetUrl. In addition, the feedback page providesGetautoredirectscript. The purpose of this function is to return the script code required for redirection through the script.

public string GetAutoRedirectScript() {
return String.Format("location.href='{0}';", TargetUrl);
}

To make the problem as simple as possible,FeedbackbasepageClassBody. This is exactly the same as what you get from the following mark.

<body runat="server" id="Body">

If you can program the text tag of a page in a simple way,FeedbackbasepageClass will find this method and automatically addOnloadProperty; otherwise, you must manually addOnloadAttribute. This attribute is required to make the feedback page work normally.

HtmlGenericControl body = FindControl(BodyId) as HtmlGenericControl;
if (body != null)
body.Attributes["onload"] = GetAutoRedirectScript();

Finally, the markup Code provided to the browser is as follows.

<body onload="location.href='lengthyop.aspx'">

Let's take a look at the steps to implement lengthy operations using the classes discussed in this article.

Reference the required assembly, and then write the following event handler for the button that triggers the operation.

void ButtonLengthyOp_Click(object sender, EventArgs e) {
LengthyAction.Start("feedback.aspx", "work.aspx");
}

Next, add the feedback page to the project. This is a regular web form page. You can modify it as described above <Body> Mark and change the base classFeedbackbasepage. After you click the button to start the process and before the result is displayed, the user interface on the feedback page is displayed, as shown in.


Figure 2 :Lengthy Operation Order

In this example, I used a cross-page sending back, which is a more common solution for particularly lengthy operations. However, this raises the problem of passing the view status and the parameters required to complete the job on the work page. You can use the query string on the work page to connect the serialized object version, or store all the content in the ASP. NET cache orSessionObject. In this case, the HTTP context cannot be used, because this operation involves multiple HTTP requests, each of which has a different project set.

Note that the URL of the feedback page contains some details about 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 it to a virtual URL that you think is more appropriate. The HTTP handler can retrieve the required information (including the name of the feedback page and work page) from the cache or session status ).

Set focus control

ASP. NET 2.0 provides an excellent new feature that allows you to specify which input control is set to focus when the page is displayed for the first time. This is a flexible function that reduces the burden of clicking start operations. For example, you can click Start to input data in the text box.

To specify the HTML component as the input focus, you need a short JavaScript code. First, declare that this is not a cutting-edge rocket science. You can easily add this JavaScript code as an embedded code to <Body> MarkedOnloadAttribute. However, in the page classSetfocusMethod to Determine the name of the focus control on the server is indeed a huge step forward. 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 displayedThefirstnameThe input control will become the focus. This method is convenient and effective, but how to encode it in ASP. NET 1.x?

Similarly, the skills for implementing this feature are already well known to the industry and can be easily searched from Google. But the question is how to integrate it into the basicsPageClass to reuse.

Let's use the following declaration to extend the msdn. Page basic class.

private string m_focusedControl;
public void SetFocus(string ctlId) {
m_focusedControl = ctlId;
}

SetfocusMethod To collect control IDs and store them in internal members. InPrerenderEvent, call another helper function to build and insert JavaScript code.

private void AddSetFocusScript ()
{
if (m_focusedControl == "")
return;
// add script to declare function
StringBuilder sb = new StringBuilder ("");
sb.Append ("<script language = javascript>");
sb.Append ("function");
sb.Append (SetFocusFunctionName);
sb.Append ("(ctl) {");
sb.Append ("if (document.forms [0] [ctl]! = null)");
sb.Append ("{document.forms [0] [ctl] .focus ();}");
sb.Append ("}");
// add script to call function
sb.Append (SetFocusFunctionName);
sb.Append ("('");
sb.Append (m_focusedControl);
sb.Append ("'); <");
sb.Append ("/"); // Disconnect in this way to avoid misunderstanding ...
sb.Append ("script>");
// Registration script (name is case sensitive)
if (! IsStartupScriptRegistered (SetFocusScriptName))
RegisterStartupScript (SetFocusScriptName, sb.ToString ());
}

JavaScript code can be constructed like a dynamic string and accumulated and stored inStringbuilderObject. The next step is to add the string to the page output. In ASP. NET, to add some client script code to the page, you must first register the code in a specific page-level collection. To this end,PageClass provides severalRegisterxxxMethod. EachRegisterxxxMethod to add the JavaScript code block to different sets so that it can be inserted to different locations in the final page tag. For example,RegisterstartupscriptInsert code before the form close mark. WhileRegisterclientscriptblockInsert script code after opening the form. The important thing is that the script must include <Script> Two tags of an element. Each script block is identified by a keyword, so that multiple server controls can use the same script block instead of sending it to the output stream twice or multiple times.

On the page, the following JavaScript code block is inserted before the close mark of the form. In this way, it will start to run immediately after initialization.

<form>
:
<script language=javascript>
function __setFocus(ctl) {
if (document.forms[0][ctl] != null) {
document.forms[0][ctl].focus();
}
}
__setFocus('TheFirstName');
</script>
</form>

By using the msdn. Page classSetfocusPublic method: you can determine the control that is used as the input focus when displaying the page in a browser at any location of the page code. More importantly, you can make this decision based on runtime conditions and/or sending back events.

Conclusion

One of the main advantages of object-oriented technology (such as ASP. NET) is that you can use inheritance extensively. By inheriting and improving the public interfaces of existing controls, you can easily create new custom server controls. In the internal class, you can replace the virtual method to change the internal behavior of the component. The application of these Object-Oriented Programming (OOP) principles to controls seems natural and common, but for classes that represent ASP. NET pages, the situation is not all at all.

However, page inheritance is widely used to construct the executable representation of each. ASPX page requested. The page containing code refers to the basicSystem. Web. UI. PageClass inheritance page. Why not define an intermediatePageClass to provide a richer foundation for application-specific pages?

This is exactly the problem described in this article. In this article, I introduced three common functions that many developers can successfully implement, namely, checking the refresh key, controlling lengthy operations, and specifying the control as the input focus, it also introduces how to encapsulate all these three functions into an all-encompassingPageClass context.

The newPageClass (msdn. Page class) to replace the basicsPageClass. This new class provides developers with more basic functions in a convenient and reusable manner. Richer FunctionsPageClass is a milestone in building a more reliable platform for ASP. NET applications. All pages of the actual application should be built from the custom class to verifyPageClass.

References

  • Programming Microsoft ASP. NET

  • Building Web solutions with ASP. NET and ADO. net

  • Introducing ASP. NET 2.0

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.