Practice for Designing Web Applications

Introduction

This article gives some very basic approach for designing a scalable, maintainable, and extensible Web application using ASP.NET and OOP approach.

Defining the Base Classes for the Application

It’s very common to have a mixture of Web pages in the application with some requiring proper user authentication to access the page and others may be accessible without proper authentication. Also, with more applications getting complex, there may be a requirement to have different levels of access to different parts of the application based on the user authentication level.

The following code sample illustrates how you can approach designing the Web application, using OOP to make the application more scalable and maintainable. In this example, consider a simple Web project with only one application. As said before, you can have a mixture of both secured Web pages (needs user authentication to access the page) and non-secured Web pages (can be accessed without user authentication). You can approach this by defining two base classes, both inheriting from System.Web.UI.Page, as shown below.

public class SecuredWebPage: System.Web.UI.Page
{
   public SecuredWebPage()
   {
   public void OnInit( System.Web.UI.Page Page)
   {
      if (Page.Session["CustomSession"] == null)
      {
         Page.Response.Redirect ("LogOn.aspx?CallingPage=" +
                                 Request.RawUrl );
      }
   }
}

public class NonSecuredWebPage: System.Web.UI.Page
{
   public NonSecuredWebPage()
   {}
   public void OnInit(System.Web.UI.Page Page)
   {
      if (Page.Session["GenericSession"] == null)
      {
         GenericSession genericSession = new GenericSession();
         genericSession.User = "Ananymous";
         Page.Session["GenericSession"] = genericSession;
      }
   )
}

These two base classes have the init event that is invoked from the pages that are used in the application passing the page itself as the argument. All you do here is check whether there is a valid Session Object available on the page. (For the non-secured pages, it’s not necessary to check any session, or you can set some generic session that might be useful when navigating the application. The Session object mentioned in the code above can be defined as the class below.

Defining the Session Class

public class CustomSession
{
   private string mstrUser = "";
   private string mstrPassword = "";
   public CustomSession()
   {}
   public string User
   {
      get{ return mstrUser;}
      set {mstrUser = value;}
   }
   public string Password
   {
      get {return mstrPassword;}
      set {mstrPassword = value;}
   }
}
public class GenericSession
{
   B private string mstrUser = "";
   B public string User
   {
      get{ return mstrUser;}
      set {mstrUser = value;}
   }
}

The Session class as defined above will be more flexible, scalable, and maintainable rather than defining the session for each property defined in the class. By having the whole class in the session, the various properties of the session can be accessed from the page as customSession = (CustomSession) Session["CustomSession"];

The above base classes, along with the session class, checks for the valid Session object, If it is not available, redirect to a page called LogOnpage.aspx with the QueryString of the URL that is calling this page. This can be used to redirect to that page after a successful logon from the log on the page. (Otherwise, you can redirect to the default page on the application as per the business need.) In this example, you are redirecting the page to the page that called this logon page.

public class LogOn : System.Web.UI.Page
{
   private void Page_Load(object sender, System.EventArgs e)
   {
      private void btnOk_Click(object sender, System.EventArgs e)
      {
         //Validate and Authenticate the User credentials here..
         CustomSession customSession = new ();
         customSession.User = txtUser.Text;
         customSession.Password = txtPassword.Text;
         Session["CustomSession"] = customSession;
         Response.Redirect (strUrl);
         this.RegisterStartupScript ("MyFunction",
            "<script language='javascript'>
            window.returnValue = 'OK';window.close();</script>");
      }
   }
}

Defining the Web Pages in the Application

With these base classes in place, all your pages in the application now can be derived from either the SecuredWebPage class or the NonSecuredWebPage class with the authentication to the page implemented by default through these base classes. So, the actual authentication need not be included in each page. And, if there are any changes in the authentication or the session that need to be changed, the change can be done in one place with minimum code change and less chance of introducing any new bugs.

The code sample for the two types of pages in the application is as follows:

public class WebForm1 : Ez.SecuredWebpage
{
   private void Page_Load(object sender, System.EventArgs e)
   {
      CustomSession customSession =
         (CustomSession) Session["CustomSession"];
      Response.Write ("The Page is logged on with User - ");
      Response.Write(customSession.User);
      Response.Write ("<BR>");
      Response.Write ("and the password is ");
      Response.Write (customSession.Password);
   }
   override protected void OnInit(EventArgs e)
   {
      base.OnInit(this);
   }
}
public class WebForm3 : Ez.NonSecuredWebPage
{
   private void Page_Load(object sender, System.EventArgs e)
   {
      GenericSession genericSession =
         (GenericSession) Session["GenericSession"];
      Response.Write ("The Page is a non secured page logged
                       on with User - ");
      Response.Write(genericSession.User);
   }
   override protected void OnInit(EventArgs e)
   {
      base.OnInit(this);
   }
}

This above approach can be used as a template when designing a Web application.

Expanding the Design Scope Across Many Applications

Most of the applications in the real world are not going to be as simple as the sample application presented above. There may be lots of applications in the project and each with different levels of authentication level for a user. When the project gets more complicated, it will be a good practice to have the base classes and the logon project defined under a folder called, for example, Common and make that referenced to all the applications that are in the project group. And, it will be a good practice to have the UI and the Data/Utility Access Layer under different folders in the project. For example, you can have a project called B Project1 and have two folders inside that as ProjectUI where all the Web pages will reside, and ProjectMI folder where you can have all the Utility access/Data access done there. This will be a good practice to follow, making it easy to maintain the code in the long run. Also, by having the MI folder for each application, the above-explained base class inheritance can be further extended by defining the B base class for each folder, which in turn is derived from the Common Base class. By doing so, you can set the Attributes for the base class in the MI folder and then call the Common with those attributes. This way, you will be able to Set or Retrieve the Session object accordingly, as per the application.

Last but not least, when designing the complex application, it will be always a good practice to have the sub-folder properly defined and group the classes accordingly. For example, you should have a Utility Folder in the application that can have many classes to handle all the I/O or Registry operations and so forth by having classes such as Fileutiltiy.cs and RegistryUtility.cs. Also, you should have a Data class from where the Data Access operations should be handled. The page should always access its corresponding MI Class in the sub-folder, which in turn will access the Common/Utility/Data Access Layers. Defining and organizing the folders and files in the project will, in most cases, decide how the project can be scaled or maintained as the business requirement grows.

The above approach is an effort to define a scalable, maintainable Web application development implementing OOP. Depending on the need, this approach can be modularized more and developing complex Web applications can be achieved with less effort.

Conclusion

I hope the above explained approach will help a lot of developers who are in the initial phase of designing and developing either a simple or complex Web application and help develop the application more effectively.

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read