In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-31 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article shares with you the content of a sample analysis of presentation layer design in PetShop. The editor thinks it is very practical, so share it with you as a reference and follow the editor to have a look.
Presentation layer Design of PetShop
The design of the presentation layer (Presentation Layer) can give the system customers the most direct experience and full confidence. Just like the acquaintance between people, the feeling of meeting for the first time will never be forgotten. If a product delivered to the customer lacks attractive features in the user interface (User Interface,UI), the interface is not friendly, and the operation is not considerate enough, even if the product has excellent performance, reasonable architecture and business logic to meet the needs of customers, it is still difficult to win the favor of customers. As the saying goes: "Buddha wants gold, people want clothes", especially for Web applications, Web web pages are like people's clothes, representing the identity and face of the whole system, and is the biggest selling point to attract "customers".
"it is better to be ugly than to hide clumsiness". As an art cell, I do not intend to make a fuss on the art design of the user interface. I will skip it in this book. This chapter focuses on the presentation layer design, from the perspective of architecture design, describes the application of patterns in the presentation layer design, the design and application of ASP.NET controls, as well as the introduction of new features of ASP.NET 2.0.
6.1 MVC mode
The most important pattern in presentation layer design is the MVC (model-view-controller) pattern. The MVC pattern was first proposed by the SmallTalk language Research Group and is widely used in user interaction applications. When Controller modifies the properties of Model according to user request (Response), Event (event) is triggered, and all View objects that depend on Model are automatically updated, and a response (Response) information is generated based on Model object and returned to Controller. In his book Enterprise Application Architecture patterns, Martin Fowler shows the whole process of applying MVC patterns, as shown in figure 6-1:
Figure 6-1 typical MVC pattern
If we split the MVC pattern into three separate parts: Model, View, and Controller, we can implement and manage the relationship between them through the GOF design pattern. In the architecture design, the domain objects of the business logic layer and the data value objects of the data access layer belong to the Model objects of the MVC schema. If you want to manage the relationship between Model and View, you can take advantage of the Observer pattern, with View as the observer, and once the property value of Model changes, the View is notified to update based on the value of Model. On the other hand, as the object that controls the user's request / response, Controller can make use of the Mediator mode to be responsible for the adjustment between request / response tasks. As for View itself, based on the idea of component-oriented design, we usually design it as components or controls, which form an object structure similar to recursive composition according to their own characteristics, so we can use Composite pattern to design View objects.
However, under the .NET platform, we do not need to implement the MVC pattern ourselves. For View objects, ASP.NET already provides commonly used Web controls, and we can also implement views by inheriting System.Web.UI.UserControl, customizing user controls, and using ASPX pages to combine Web controls. ASP.NET defines the System.Web.UI.Page class, which is equivalent to the Controller object of the MVC schema and can handle the user's request. Due to the use of codebehind technology, the display of the user interface is completely separated from the UI implementation logic, that is to say, the View object and the Controller object become two relatively independent parts, which is conducive to the reusability of the code. Compared with ASP, this programming method is more in line with the programming habits of developers, and is conducive to the division of labor and cooperation between developers and UI designers. As for Model objects, they are domain objects of the business logic layer. In addition, the .NET platform provides DataSet objects through ADO.NET to facilitate binding to data sources of Web controls.
6.2Application of Page Controller model
Taking a general view of the design of the presentation layer of PetShop, making full use of the technical characteristics of ASP.NET, controlling and displaying the view through Web pages and user controls, and using codebehind technology to add the domain objects of the business logic layer to the implementation logic of the presentation layer, a typical Page Controller pattern is coming out.
Page Controller pattern is one of the most important presentation layer patterns of Martin Fowler in Enterprise Application Architecture pattern. Under the .NET platform, the implementation of the Page Controller pattern is very simple, taking Products.aspx pages as an example. First, on the aspx page, make the following settings:
Aspx pages inherit from the System.Web.UI.Page class. The Page class object has the features of the Web control by inheriting the System.Web.UI.Control class, and it also implements the IHttpHandler interface. As an interface for ASP.NET to process HTTP Web requests, the following definitions are provided:
[AspNetHostingPermission (SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal), AspNetHostingPermission (SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] public interface IHttpHandler {void ProcessRequest (HttpContext context); bool IsReusable {get;}}
The Page class implements the ProcessRequest () method, which allows you to set the Request and Response properties of the Page object to control the user request / corresponding. The Page class then associates View with Model through the Load event inherited from the Control class, as shown in Products.aspx.cs:
Public partial class Products: System.Web.UI.Page {protected void Page_Load (object sender, EventArgs e) {/ / get page header and title Page.Title = WebUtility.GetCategoryName (Request.QueryString ["categoryId"]);}}
The event mechanism happens to be the implementation of the observer pattern. When the Load event of the ASPX page is fired, the system obtains the Category value through the GetCategoryName () method of the WebUtility class (which is described in detail in Chapter 28) and displays it on the Title of the page. The Page object, as a Controller, acts as a mediator to coordinate the relationship between View and Model.
Because ASPX pages can also contain Web controls, these control objects are also used as View objects, and they are controlled by Page type objects. For example, in the CheckOut.aspx page, when the user makes a request for CheckOut, wzdCheckOut, as the System.Web.UI.WebControls.Winzard control type, triggers the FinishButtonClick event at the end of the wizard process, and calls the Insert () method of the domain object Order in that event, as shown below:
Public partial class CheckOut: System.Web.UI.Pageprotected void wzdCheckOut_FinishButtonClick (object sender, WizardNavigationEventArgs e) {if (Profile.ShoppingCart.CartItems.Count > 0) {if (Profile.ShoppingCart.Count > 0) {/ / display ordered items CartListOrdered.Bind (Profile.ShoppingCart.CartItems); / / display total and credit card information ltlTotalComplete.Text = ltlTotal.Text; ltlCreditCardComplete.Text = ltlCreditCard.Text / / create order OrderInfo order = new OrderInfo (int.MinValue, DateTime.Now, User.Identity.Name, GetCreditCardInfo (), billingForm.Address, shippingForm.Address, Profile.ShoppingCart.Total, Profile.ShoppingCart.GetOrderLineItems (), null); / / insert Order newOrder = newOrder (); newOrder.Insert (order); / / destroy cart Profile.ShoppingCart.Clear (); Profile.Save ();} else {lblMsg.Text = "
Can not process the order. Your cart is empty.
Continue shopping
"; wzdCheckOut.Visible = false;}}
The relationship between Model and View is typically expressed in the above code. It obtains the property value of the control and passes it to the data value object OrderInfo as a parameter value, thus creating an order object using the order information generated on the page, and then inserting the OrderInfo object into the data table by calling the Inser () method of the domain object Order. In addition, it determines the data item of the domain object ShoppingCart, and displays a UI prompt on the page if its value is equal to 0. At this point, the content of the View determines the value of the Model, while the Model value in turn determines what the View displays.
6.3 ASP.NET controls
ASP.NET control is the most important part of View object, it makes full use of object-oriented design idea, through encapsulation and inheritance to build control objects, so that users can reuse these controls and even customize their own controls when developing Web pages. In chapter 8, I have introduced the design idea of controls in .NET Framework, and implemented the control tree by introducing a "composite mode" Composite pattern. In ASP.NET controls, System.Web.UI.Control is the root of this control tree. It defines the properties, methods, and events common to all ASP.NET controls, and is responsible for managing and controlling the entire execution life cycle of the control.
The Control base class does not contain specific functionality of UI, and if you need to provide method properties related to UI, you need to derive from the System.Web.UI.WebControls.WebControl class. This class is actually a subclass of the Control class, but it appends properties such as ForeColor, BackColor, Font, and so on.
In addition, another important class is System.Web.UI.UserControl, the user control class, which is also a subclass of the Control class. We can customize some user controls derived from UserControl. In the Design environment of Visual Studio, we can combine various types of controls into a custom user control by dragging controls, or we can add new properties and methods to custom user control classes in codebehind mode.
The hierarchy of the entire ASP.NET control class is shown in figure 6-2:
Figure 6-2 hierarchical structure of the ASP.NET control class
The execution life cycle of the ASP.NET control is shown in Table 6-1:
Stage
Control needs to be performed
Method or event to be overridden
Initialization
Initializes the settings required during the life cycle of the incoming Web request.
Init event (OnInit method)
Load View Stat
At the end of this phase, the ViewState property of the control is automatically populated, and the control can override the default implementation of the LoadViewState method to restore in a custom state.
LoadViewState method
Processing postback data
Process incoming form data and update properties accordingly.
Note: only controls that handle postback data participate in this phase.
LoadPostData method (if IPostBackDataHandler has been implemented)
Load
Perform operations common to all requests, such as setting up database queries. At this point, the server control in the tree has been created and initialized, the state has been restored, and the form control reflects the client's data.
Load event (OnLoad method)
Send postback change notification
Raises a change event in response to a state change between the current and previous postback.
Note: only controls that raise postback change events participate in this phase.
RaisePostDataChangedEvent method (if IPostBackDataHandler has been implemented)
Handle postback events
Handles the client event that caused the postback and raises the corresponding event on the server.
Note: only controls that handle postback events participate in this phase.
RaisePostBackEvent method (if IPostBackEventHandler has been implemented)
Pre-presentation
Perform any updates before rendering the output. Changes to the state of the control can be saved at the pre-rendering stage, while changes made during the rendering phase are lost.
PreRender event (OnPreRender method)
Save statu
After this stage, the ViewState property of the control is automatically maintained in the string object. This string object is sent to the client and sent back as a hidden variable. To improve efficiency, controls can override the SaveViewState method to modify the ViewState property.
SaveViewState method
Present
Generate output that is presented to the client.
Render method
Disposal
Perform all final cleanup operations before destroying the control. References to expensive resources, such as database links, must be released at this stage.
Dispose method
Unloading
Perform all final cleanup operations before destroying the control. Control authors typically perform cleanup in Dispose without handling this event.
UnLoad event (On UnLoad method)
Table 6-1 execution lifecycle of ASP.NET controls
Here, the control design takes advantage of the Template Method pattern, and the Control base class provides most of the protected virtual methods, leaving it for its subclasses to override its methods. Taking PetShop 4.0 as an example, two ASP.NET controls are defined, both of which belong to subclasses of System.Web.UI.WebControls.WebControl. Where the CustomList control is derived from the System.Web.UI.WebControls.DataList,CustomGrid control and from System.Web.UI.WebControls.Repeater.
Because both controls change the way their parent class controls are rendered, we can customize the control by overriding the parent class's Render virtual method. For example, the CustomGrid control:
Public class CustomGrid: Repeater... / Static constants protected const string HTML1 = ""; protected const string HTML2 = ""; protected const string HTML3 = ""; protected const string HTML4 = ""; private static readonly Regex RX = new Regex (@ "^ & page=\ d +", RegexOptions.Compiled); private const string LINK_PREV = ""; private const string KEY_PAGE = "page"; private const string COMMA = "?"; private const string AMP = "&" Override protected void Render (HtmlTextWriter writer) {/ / Check there is some data attached if (ItemCount = = 0) {writer.Write (emptyText); return;} / / Mask the query string query = Context.Request.Url.Query.Replace (COMMA, AMP); query = RX.Replace (query, string.Empty); / / Write out the first part of the control, the table header writer.Write (HTML1); / / Call the inherited method base.Render (writer); / / Write out a table row closure writer.Write (HTML2) / / Determin whether next and previous buttons are required / / Previous button? If (currentPageIndex > 0) writer.Write (string.Format (LINK_PREV, (currentPageIndex-1) + query); / / Close the table data tag writer.Write (HTML3); / / Next button? If (currentPageIndex
< PageCount) writer.Write(string.Format(LINK_MORE, (currentPageIndex + 1) + query)); //Close the table writer.Write(HTML4); } 由于CustomGrid继承自Repeater控件,因而它同时还继承了Repeater的DataSource属性,这是一个虚属性,它默认的set访问器属性如下: public virtual object DataSource{ get {… } set { if (((value != null) && !(value is IListSource)) && !(value is IEnumerable)) { throw new ArgumentException(SR.GetString("Invalid_DataSource_Type", new object[] { this.ID })); } this.dataSource = value; this.OnDataPropertyChanged(); }} 对于CustomGrid而言,DataSource属性有着不同的设置行为,因而在定义CustomGrid控件的时候,需要改写DataSource虚属性,如下所示: private IList dataSource;private int itemCount;override public object DataSource { set { //This try catch block is to avoid issues with the VS.NET designer //The designer will try and bind a datasource which does not derive from ILIST try { dataSource = (IList)value; ItemCount = dataSource.Count; } catch { dataSource = null; ItemCount = 0; } }} 当设置的value对象值不为IList类型时,set访问器就将捕获异常,然后将dataSource字段设置为null。 由于我们改写了DataSource属性,因而改写Repeater类的OnDataBinding()方法也就势在必行。此外,CustomGrid还提供了分页的功能,我们也需要实现分页的相关操作。与DataSource属性不同,Repeater类的OnDataBinding()方法实际上是继承和改写了Control基类的OnDataBinding()虚方法,而我们又在此基础上改写了Repeater类的OnDataBinding()方法: override protected void OnDataBinding(EventArgs e) { //Work out which items we want to render to the page int start = CurrentPageIndex * pageSize; int size = Math.Min(pageSize, ItemCount - start); IList page = new ArrayList(); //Add the relevant items from the datasource for (int i = 0; i < size; i++) page.Add(dataSource[start + i]); //set the base objects datasource base.DataSource = page; base.OnDataBinding(e);} 此外,CustomGrid控件类还增加了许多属于自己的属性和方法,例如PageSize、PageCount属性以及SetPage()方法等。正是因为ASP.NET控件引入了Composite模式与Template Method模式,当我们在自定义控件时,就可以通过继承与改写的方式来完成控件的设计。自定义ASP.NET控件一方面可以根据系统的需求实现特定的功能,也能够最大限度地实现对象的重用,既可以减少编码量,同时也有利于未来对程序的扩展与修改。 在PetShop 4.0中,除了自定义了上述WebControl控件的子控件外,最主要的还是利用了用户控件。在Controls文件夹下,一共定义了11个用户控件,内容涵盖客户地址信息、信用卡信息、购物车信息、期望列表(Wish List)信息以及导航信息、搜索结果信息等。它们相当于是一些组合控件,除了包含了子控件的方法和属性外,也定义了一些必要的UI实现逻辑。以ShoppingCartControl用户控件为例,它会在该控件被呈现(Render)之前,做一些数据准备工作,获取购物车数据,并作为数据源绑定到其下的Repeater控件: public partial class ShoppingCartControl : System.Web.UI.UserControl protected void Page_PreRender(object sender, EventArgs e) { if (!IsPostBack) { BindCart(); } } private void BindCart() { ICollection cart = Profile.ShoppingCart.CartItems; if (cart.Count >0) {repShoppingCart.DataSource = cart; repShoppingCart.DataBind (); PrintTotal (); plhTotal.Visible = true;} else {repShoppingCart.Visible = false; plhTotal.Visible = false; lblMsg.Text = "Your cart is empty.";}}
Under the ShoppingCart page, we can add the user control, as shown below:
Because the ShoppingCartControl user control has implemented the logic for rendering shopping cart data, then in ShoppingCart.aspx.cs, you can not be responsible for this logic, in the process of fully completing object reuse, while achieving the purpose of separation of responsibilities. The designer of the user control and the page designer can complete their own design separately without interfering with each other. Especially for the page designer, he can be a single UI designer, only need to pay attention to whether the user interface is beautiful and friendly, and ignore the call and operation of domain objects in the presentation layer, and the code of the whole page also appears to be clear in structure, clear in logic, and undoubtedly "clean" a lot.
6.4 what's new in ASP.NET 2.0
Because PetShop 4.0 is an e-commerce system based on .NET Framework 2.0 platform, it also introduces many new features of ASP.NET 2.0 in the presentation layer, such as MemberShip, Profile, Master Page, login controls and so on. Next, I will introduce their implementation in combination with the design of PetShop 4.0.
6.4.1 Profile featur
The function provided by Profile is a personalized service for users. In ASP.NET version 1.x, we can use Session, Cookie and other methods to store user status information. However, the Session object has a lifetime, and once the lifetime expires, the value retained by the object will be invalidated. Cookie saves user information in the client, it has certain security risks, and some important information can not be stored in Cookie. Once the client forbids the use of Cookie, the function will lose the function of the application.
The emergence of Profile solves the above annoyance, which can save the user's personalized information in the specified database. The Profile feature of ASP.NET 2.0 supports Access database and SQL Server database by default, and if you need to support other databases, you can write related ProfileProvider classes. The Profile object is strongly typed, and we can establish properties for user information. Take PetShop 4.0as an example, it establishes ShoppingCart, WishList, and AccountInfo properties.
Because the Profile function needs to access the database, the module structure similar to the data table such as Product is defined in the data access layer (DAL). First, an IProfileDAL interface module is defined, which includes the interface IPetShopProfileProvider:
Public interface IPetShopProfileProvider {AddressInfo GetAccountInfo (string userName, string appName); void SetAccountInfo (int uniqueID, AddressInfo addressInfo); IList GetCartItems (string userName, string appName, bool isShoppingCart); void SetCartItems (int uniqueID, ICollection cartItems, bool isShoppingCart); void UpdateActivityDates (string userName, bool activityOnly, string appName); int GetUniqueID (string userName, bool isAuthenticated, bool ignoreAuthenticationType, string appName); int CreateProfileForUser (string userName, bool isAuthenticated, string appName); IList GetInactiveProfiles (int authenticationOption, DateTime userInactiveSinceDate, string appName); bool DeleteProfile (string userName, string appName) IList GetProfileInfo (int authenticationOption, string usernameToMatch, DateTime userInactiveSinceDate, string appName, out int totalRecords);}
Because PetShop version 4.0 supports SQL Server and Oracle databases respectively, it defines two different PetShopProfileProvider classes, implements the IPetShopProfileProvider interface, and places them in two different modules, SQLProfileDAL and OracleProfileDAL. See the source code of PetShop 4.0for a specific implementation.
Similarly, PetShop 4.0 introduces the factory pattern for Profile, defining the module ProfileDALFActory, and the factory class DataAccess is defined as follows:
Public sealed class DataAccess {private static readonly string profilePath = ConfigurationManager.AppSettings ["ProfileDAL"]; public static PetShop.IProfileDAL.IPetShopProfileProvider CreatePetShopProfileProvider () {string className = profilePath + ".PetShopProfileProvider"; return (PetShop.IProfileDAL.IPetShopProfileProvider) Assembly.Load (profilePath) .CreateInstance (className);}}
In the business logic layer (BLL), the module Profile is defined separately, which adds assemblies to the BLL, IProfileDAL, and ProfileDALFactory modules. In this module, the sealing class PetShopProfileProvider is defined, which inherits from the System.Web.Profile.ProfileProvider class, which is the Provider base class of Profile and is used to implement related profile services in custom configuration files. In the PetShopProfileProvider class, some methods in the parent class ProfileProvider are overridden, such as Initialize (), GetPropertyValues (), SetPropertyValues (), DeleteProfiles (), and so on. In addition, Get and Set methods are provided for the ShoppingCart, WishList, and AccountInfo properties. As for the specific implementation of Provider, call the concrete type object created by the factory class DataAccess, as shown below:
Private static readonly IPetShopProfileProvider dal = DataAccess.CreatePetShopProfileProvider ()
After the PetShop.Profile.PetShopProfileProvider class is defined, you can configure the following configuration section in the web.config configuration file:
In the configuration file, ShoppingCartProvider, WishListProvider, and AccountInfoProvider are defined for the ShoppingCart, WishList, and AccountInfo attributes (their types are PetShop.BLL.Cart, PetShop.BLL.Cart, and PetShop.Model.AddressInfo, respectively), and their types are all PetShop.Profile.PetShopProfileProvider types. The type of database in which Profile information is stored is determined by the following configuration section:
The key value is the value of ProfileDAL, which is obtained by Profile's factory class PetShop.ProfileDALFactory.DataAccess when it uses reflection technology to create IPetShopProfileProvider-type objects.
In the presentation layer, you can use the Profile attribute of the page to access the personalization attribute of the user. For example, in the codebehind code ShoppingCart.aspx.cs of the ShoppingCart page, call the ShoppingCart attribute of Profile:
Public partial class ShoppingCart: System.Web.UI.Page {protected void Page_PreInit (object sender, EventArgs e) {if (! IsPostBack) {string itemId = Request.QueryString ["addItem"]; if (! string.IsNullOrEmpty (itemId)) {Profile.ShoppingCart.Add (itemId); Profile.Save (); / / Redirect to prevent duplictations in the cart if user hits "Refresh" Response.Redirect ("~ / ShoppingCart.aspx", true);}
In the above code, where does the value of the Profile attribute come from? In fact, after we configure Profile in the web.config configuration file, start the Web application, and ASP.NET creates an instance of the ProfileCommon class based on the relevant configuration in the configuration file. This class inherits from the System.Web.Profile.ProfileBase class. The GetPropertyValue and SetPropertyValue methods inherited from the parent class are then called to retrieve and set the property values of the configuration file. ASP.NET then sets the created ProfileCommon instance to the Profile attribute value of the page. Therefore, we can obtain the ShoppingCart property of Profile through IntelliSense, and we can also update the data source of Profile according to the attribute value by using the Save () method that ProfileCommon inherits from the ProfileBase class.
6.4.2 Membership featur
Instead of taking advantage of the advanced features of Membership, PetShop 4.0 directly binds the Membership feature to the new login controls in ASP.NET 2.0. Because the .NET Framework 2.0 already defines a SqlMembershipProvider for SQL Server, it is easier for PetShop 4.0 to implement Membership than to implement Profile, simply by defining a MembershipProvider for the Oracle database. In the PetShop.Membership module, the OracleMembershipProvider class is defined, which inherits from the System.Web.Security.MembershipProvider abstract class.
The implementation of the OracleMembershipProvider class is of great reference value. If we need to define our own MembershipProvider class, we can refer to the implementation of this class.
In fact, the implementation of the OracleMemberShip class is not complex. In this class, it mainly implements related behaviors for users and their security. Since virtual methods for related operations have been defined in the parent class MembershipProvider, what we need to do is to override these virtual methods. Because all Membership-related information is stored in a database, the main difference between OracleMembershipProvider and SqlMembershipProvider classes lies in access to the database. As far as SQL Server is concerned, we use aspnet_regsql tools to establish relevant data tables and stored procedures for Membership. Perhaps because of intellectual property rights, Microsoft does not provide similar tools for Oracle databases, so we need to create our own data tables for membership. In addition, since there is no stored procedure to create the Oracle database, the implementation in the OracleMembershipProvider class invokes the SQL statement directly. Taking the CreateUser () method as an example, excluding the complicated parameter judgment and security judgment, the implementation of the SqlMembershipProvider class is as follows:
Public override MembershipUser CreateUser (string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status) {MembershipUser user1; / / previous code; try {SqlConnectionHolder holder1 = null; try {holder1 = SqlConnectionHelper.GetConnection (this._sqlConnectionString, true); this.CheckSchemaVersion (holder1.Connection); DateTime time1 = this.RoundToSeconds (DateTime.UtcNow); SqlCommand command1 = new SqlCommand ("dbo.aspnet_Membership_CreateUser", holder1.Connection) Command1.CommandTimeout = this.CommandTimeout; command1.CommandType = CommandType.StoredProcedure; command1.Parameters.Add (this.CreateInputParam ("@ ApplicationName", SqlDbType.NVarChar, this.ApplicationName); command1.Parameters.Add (this.CreateInputParam ("@ UserName", SqlDbType.NVarChar, username)); command1.Parameters.Add (this.CreateInputParam ("@ Password", SqlDbType.NVarChar, text2)); command1.Parameters.Add ("@ PasswordSalt", SqlDbType.NVarChar, text1)) Command1.Parameters.Add (this.CreateInputParam ("@ Email", SqlDbType.NVarChar, email); command1.Parameters.Add ("@ PasswordQuestion", SqlDbType.NVarChar, passwordQuestion); command1.Parameters.Add (this.CreateInputParam ("@ PasswordAnswer", SqlDbType.NVarChar, text3)); command1.Parameters.Add (this.CreateInputParam ("@ IsApproved", SqlDbType.Bit, isApproved); command1.Parameters.Add ("@ UniqueEmail", SqlDbType.Int, this.RequiresUniqueEmail? 1: 0)) Command1.Parameters.Add (this.CreateInputParam ("@ PasswordFormat", SqlDbType.Int, (int) this.PasswordFormat); command1.Parameters.Add (this.CreateInputParam ("@ CurrentTimeUtc", SqlDbType.DateTime, time1)); SqlParameter parameter1 = this.CreateInputParam ("@ UserId", SqlDbType.UniqueIdentifier, providerUserKey); parameter1.Direction = ParameterDirection.InputOutput; command1.Parameters.Add (parameter1); parameter1 = new SqlParameter ("@ ReturnValue", SqlDbType.Int); parameter1.Direction = ParameterDirection.ReturnValue Command1.Parameters.Add (parameter1); command1.ExecuteNonQuery (); int num3 = (parameter1.Value! = null)? ((int) parameter1.Value):-1; if ((num3)
< 0) || (num3 >11) {num3 = 11;} status = (MembershipCreateStatus) num3; if (num3! = 0) {return null;} providerUserKey = new Guid (command1.Parameters ["@ UserId"] .Value.ToString ()); time1 = time1.ToLocalTime (); user1 = new MembershipUser (this.Name, username, providerUserKey, email, passwordQuestion, null, isApproved, false, time1, new DateTime (0x6da, 1, 1)) } finally {if (holder1! = null) {holder1.Close (); holder1 = null;} catch {throw;} return user1;}
In the code, aspnet_Membership_CreateUser is the stored procedure created by the aspnet_regsql tool for membership, and its function is to create a user.
The definition of the CreateUser () method in the OracleMembershipProvider class is as follows:
Public override MembershipUser CreateUser (string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object userId, out MembershipCreateStatus status) {/ / preceding code; / / Create connection OracleConnection connection = new OracleConnection (OracleHelper.ConnectionStringMembership); connection.Open (); OracleTransaction transaction = connection.BeginTransaction (IsolationLevel.ReadCommitted); try {DateTime dt = DateTime.Now; bool isUserNew = true; / / Step 1: Check if the user exists in the Users table: create if not int uid = GetUserID (transaction, applicationId, username, true, false, dt, out isUserNew) If (uid = = 0) {/ / User not created successfully! Status = MembershipCreateStatus.ProviderError; return null;} / / Step 2: Check if the user exists in the Membership table: Error if yes. If (IsUserInMembership (transaction, uid)) {status = MembershipCreateStatus.DuplicateUserName; return null;} / / Step 3: Check if Email is duplicate if (IsEmailInMembership (transaction, email, applicationId)) {status = MembershipCreateStatus.DuplicateEmail; return null;} / / Step 4: Create user in Membership table int pFormat = (int) passwordFormat; if (! InsertUser (transaction, uid, email, pass, pFormat, salt, ",", isApproved, dt)) {status = MembershipCreateStatus.ProviderError; return null } / / Step 5: Update activity date if user is not new if (! isUserNew) {if (! UpdateLastActivityDate (transaction, uid, dt)) {status = MembershipCreateStatus.ProviderError; return null;}} status = MembershipCreateStatus.Success; return new MembershipUser (this.Name, username, uid, email, passwordQuestion, null, isApproved, false, dt, DateTime.MinValue); catch (Exception) {if (status = = MembershipCreateStatus.Success) status = MembershipCreateStatus.ProviderError; throw } finally {if (status = = MembershipCreateStatus.Success) transaction.Commit (); else transaction.Rollback (); connection.Close (); connection.Dispose ();}}
In the code, the InsertUser () method is responsible for the creation of the user, and before that you need to determine whether the created user already exists. The definition of the InsertUser () method is as follows:
Private static bool InsertUser (OracleTransaction transaction, int userId, string email, string password, int passFormat, string passSalt, string passQuestion, string passAnswer, bool isApproved, DateTime dt) {string insert = "INSERT INTO MEMBERSHIP (USERID, EMAIL, PASSWORD, PASSWORDFORMAT, PASSWORDSALT, PASSWORDQUESTION, PASSWORDANSWER, ISAPPROVED, CREATEDDATE, LASTLOGINDATE, LASTPASSWORDCHANGEDDATE) VALUES (: UserID,: Email,: Pass,: PasswordFormat,: PasswordSalt,: PasswordQuestion,: PasswordAnswer,: IsApproved, CDate,: LLDate,: LPCDate)" OracleParameter [] insertParms = {new OracleParameter (": UserID", OracleType.Number, 10), new OracleParameter (": Email", OracleType.VarChar, 128), new OracleParameter (": Pass", OracleType.VarChar, 128), new OracleParameter (": PasswordFormat", OracleType.Number, 10), new OracleParameter (": PasswordSalt", OracleType.VarChar, 128), new OracleParameter (": PasswordQuestion", OracleType.VarChar, 256), new OracleParameter (": PasswordAnswer", OracleType.VarChar, 128), new OracleParameter (": IsApproved", OracleType.VarChar, 1) New OracleParameter (": CDate", OracleType.DateTime), new OracleParameter (": LLDate", OracleType.DateTime), new OracleParameter (": LPCDate", OracleType.DateTime)} InsertParms [0] .value = userId; insertParms [1] .value = email; insertParms [2] .value = password; insertParms [3] .value = passFormat; insertParms [4] .value = passSalt; insertParms [5] .value = passAnswer; insertParms [7] .value = OracleHelper.OraBit (isApproved); insertParms [8] .value = dt; insertParms [9] .value = dt; insertParms [10] .value = dt; if (OracleHelper.ExecuteNonQuery (transaction, CommandType.Text, insert, insertParms)! = 1) return false; else return true }
After you have established the Provider class for Membership, you also need to configure the relevant configuration section in the configuration file, such as the configuration of SqlMembershipProvider:
For OracleMembershipProvider, the configuration is roughly similar:
For the meaning of configuring section properties, you can refer to relevant documents such as MSDN.
6.4.3 ASP.NET login control
The so-called login control here does not mean a control, but a new set of controls provided by ASP.NET 2.0 to solve the problem of user login. The login control is integrated with Membership to realize the processing of user login quickly and easily. ASP.NET login controls include Login controls, LoginView controls, LoginStatus controls, LoginName controls, PasswordRescovery controls, CreateUserWizard controls, and ChangePassword controls.
PetShop 4.0 is like a perfect tutorial to demonstrate the use of login controls. We can see how to use the ASP.NET login control from pages such as SignIn, NewUser, and so on. For example, in SignIn.aspx, the Login control is used. In this control, you can include TextBox, Button, and other types of controls, and the usage is as follows:
Another example is the use of the CreateUserWizard control in NewUser.aspx:
After using the login control, we do not need to write the code related to the user login, the login control has completed the related functions for us, which greatly simplifies the design and implementation of the system.
6.4.4 Master Page featur
Master Page is equivalent to a unified template for the entire Web site, and the established Master Page file extension is .master. It can contain static text, html elements, and server controls. Master Page is recognized by a special @ Master instruction, such as:
Using Master Page, you can create a uniform style for your Web site, and you can easily use it to create a set of controls and code, and then apply it to a set of pages. For pages with similar styles and functions, Master Page can be used to centrally process them as Master Page, and once modified, they can be updated in one place.
In PetShop 4.0, a MasterPage named MasterPage.master is established, which contains header, LoginView controls, navigation menus, and html elements for rendering content, as shown in figure 6-3:
Figure 6-3 Master Page of PetShop 4.0
The @ Master directive is defined as follows:
MasterPage also uses codebehind technology. Take the MasterPage of PetShop 4.0 as an example, the code of codebehind is placed in the file MasterPage.master.cs:
Public partial class MasterPage: System.Web.UI.MasterPage {private const string HEADER_PREFIX = ".NET Pet Shop:: {0}"; protected void Page_PreRender (object sender, EventArgs e) {ltlHeader.Text = Page.Header.Title; Page.Header.Title = string.Format (HEADER_PREFIX, Page.Header.Title);} protected void btnSearch_Click (object sender, EventArgs e) {WebUtility.SearchRedirect (txtSearch.Text);}}
Notice that the MasterPage page no longer inherits from System.Web.UI.Page, but inherits the System.Web.UI.MasterPage class. Unlike the Page class, which inherits the TemplateControl class, it is a subclass of the UserControl class. Therefore, the valid instructions that can be applied to Master Page are the same as those available to UserControl, such as AutoEventWireup, ClassName, CodeFile, EnableViewState, WarningLevel, and so on.
Each MasterPage-related content page must reference the relevant MasterPage in the MasterPageFile attribute of the @ Page directive. For example, the @ Page directive for the CheckOut content page in PetShop 4.0 is defined as follows:
MasterPage can be nested. For example, if we have established the parent MasterPage page Parent.master, then in the child MasterPage, we can specify the parent MasterPage using the master attribute:
The content page can point to Parent.master or Child.master pages as appropriate.
Although MasterPage is created declaratively for the most part, we can also create a class that inherits System.Web.UI.MasterPage, thus completing the programmatic creation of MasterPage. But in this way, you should create a .master file at the same time. In addition, the call to Master Page can also be done programmatically, such as adding Master Page dynamically, and we override the Page_PreInit () method of the content page, as follows:
Void Page_PreInit (Object sender, EventArgs e) {this.MasterPageFile = "~ / NewMaster.master";}
The Page_PreInit () method is overridden because Master Page merges during the content page initialization phase, that is, the Master Page allocation is completed during the PreInit phase.
The new features introduced by ASP.NET 2.0 are not limited to the above introduction. For example, Theme, Wizard controls and other new features have also been widely used in PetShop 4.0. Although ASP.NET 2.0 brings forth the new in time and improves the design of the presentation layer, as a part of ASP.NET 2.0, they only make up for and improve the lack of the existing framework, belong to the category of "icing on the cake", but play a very limited role in promoting the whole presentation layer design technology.
It was not until the advent of AJAX (Asynchronous JavaScript and XML) that the whole situation changed greatly. Although AJAX technology has a bit of the flavor of "new wine in old bottles", it has been a king from the beginning of its birth and has the potential to sweep the world. Various frameworks that support AJAX technology are springing up like bamboo shoots after a spring rain, supporting the prosperity of a hundred flowers blooming, and aggressively creating a situation that is exclusive to AJAX. Nowadays, AJAX has become the mainstream development technology of Web applications, and many big crocodiles in the industry are grinning their teeth and starting to land on this new territory. For example, IBM, Oracle, Yahoo and other companies have launched open source AJAX projects. Microsoft did not want to lag behind and launched ASP.NET AJAX in time, which is an ASP.NET-based AJAX framework, which includes ASP.NET AJAX server components and ASP.NET AJAX client components, and integrated in Visual Studio, providing a powerful AJAX application environment for ASP.NET developers.
I can't predict the future of AJAX technology yet, but only from the point of view of presentation layer design, AJAX technology also brings a new revolution. Maybe we can look forward to the future of PetShop 5.0, which can bring more surprises in the design of the presentation layer.
Thank you for reading! This is the end of this article on "sample Analysis of presentation layer Design in PetShop". I hope the above content can be of some help to you, so that you can learn more knowledge. if you think the article is good, you can share it for more people to see!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.