The Artima Developer Community
Sponsored Link

.NET Buzz Forum
Building Frameworks Tip 6

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Jonathan Crossland

Posts: 630
Nickname: jonathanc
Registered: Feb, 2004

Jonathan Crossland is a software architect for Lucid Ocean Ltd
Building Frameworks Tip 6 Posted: Apr 23, 2004 7:49 PM
Reply to this message Reply

This post originated from an RSS feed registered with .NET Buzz by Jonathan Crossland.
Original Post: Building Frameworks Tip 6
Feed Title: Jonathan Crossland Weblog
Feed URL: http://www.jonathancrossland.com/syndication.axd
Feed Description: Design, Frameworks, Patterns and Idioms
Latest .NET Buzz Posts
Latest .NET Buzz Posts by Jonathan Crossland
Latest Posts From Jonathan Crossland Weblog

Advertisement

TIP: Tips for creating a Framework from an existing ASP.NET Application

This is going to be more of a 'ad-hoc' guide than a single tip. I want to merely point out how easy it is to Harvest a framework in a relatively short period of time.
I spent 9 hours doing all of this guide, and I now have the IBuySpyStore application separated
Application part and Framework part It is just the start, but is now ready to evolve into its separate areas properly.
Why did I choose to do this, because I wanted to see how long it would take to Harvest it, rather than start from scratch
I think I saved at least 3 days work, by refactoring the existing sample. I did not have to create the database, queries, initial logic (cart, checkout etc) or the Stylesheet and so on.

Getting Started

The problem with IBuySpyStore is that it is code written to teach ASP.NET functionality. For this purpose it has lots of ASPX Pages, some UserControls, and shows off some functionality like Forms Authentication.

The first thing to do in this situation is to discover what is generic, and what is not. Luckily, the IBuySpyStore source code, can be used for any product, so it is already quite general in its code.
Here is a starting point of what to identify
  • Infrastructure elements
  • Extensible Elements
Here is a quick division of the some elements of the Application. Note that some appear in both.
Infrastructure
  • Login.aspx
  • Register.aspx
  • Account.aspx
  • ErrorPage.aspx
  • Cart.aspx
Extensible
  • Login.aspx
  • Register.aspx
  • ErrorPage.aspx
  • Cart.aspx
  • ProductList.aspx
  • ProductDetails.aspx
  • Cart.aspx
Currently the code is basically all in the root and within ASPX pages. The first thing to do is to create two temporary folders under the root.
Two folders, Infrastructure and Extensible would be good temporary folders.

Refactoring the Application
The trick is to gently migrate the Application into two distinct sections. The code will basically remain the same, except for where you are repairing links, paths and code that keeps the application running.

Giving Control to the Framework
A Framework should have control of flow and context (see Tip 5). Since it is far easier to update a single page with logic, styles and functionality, it is recommended that some form of a PageController pattern be used.

I prefer loading UserControls, so I will show you a quick way to do it.

Simply add a System.Web.UI.WebControls.PlaceHolder control to the Default.aspx page.
In the load event of the Default.aspx page, add the following code:
if (Request["View"] !=null)
            {
                string view = Request["View"].ToString();

                if (view!="")
                {
                    _ContentArea.Controls.Add(LoadControl(GetVirtualUserContentDirectory() + view + ".ascx"));
                }
            }
            else
            {
                
                _ContentArea.Controls.Add(LoadControl(GetVirtualUserContentDirectory() + "Home.ascx"));
            }
Where _ContentArea is a PlaceHolder Control (System.Web.UI.WebControls.PlaceHolder)
and GetExtensibleDirectory() is a method where you obtain the Extensible directory you created earlier. Until you have a place for it (you will still refactor more later), you can create a simple method in the Default.aspx page.
public string GetExtensibleDirectory()
{
    return "Extensible/";
}

This will provide you with functionality to load a UserControl into the placeholder by looking at the "View" in the QueryString. Therefore, links must change. The main links are those in the menu. Instead of pointing to Cart.Aspx, it will be default.aspx?View=Cart
You should updated all the links on the default.aspx page and the menu usercontrols it loads.
Next you must drag the ASPX pages, such as ProductList.aspx, Login.Aspx to the appropriate directory. One of the two new folders you created.
Once all the pages are moved into one or other new folder, you must convert the ASPX page to a ASCX page.
This is relatively straight forward. As an example, I will convert login.aspx.
  • Rename Login.aspx to Login.ascx
  • Change the @ Page directive to @ Control
    //before
    <%@ Page Language="c#" CodeBehind="OrderDetails.aspx.cs" AutoEventWireup="false" Inherits="IBuySpyStore.OrderDetails" %>

    //after
    <%@ Control Language="c#" AutoEventWireup="false" Codebehind="IBuySpyStore.ascx.cs" Inherits="IBuySpyStore.OrderDetails" TargetSchema="http://schemas.microsoft.com/intellisense/ie5" %>
  • Change the base class from System.Web.UI.Page to System.Web.UI.UserControl
  • Inside the codebehind change Page.Init to this.Init. There may also be code that uses a Type on the Page object which is now not used, you will have to add this.Page.* instead
  • Remove the surrounding HTML and Body tags
I did this in three hours, including fixing all the links to the new paths and changing the Forms Authentication to work with UserControls (see deny users post.

Web.Config refers to Login.aspx - change to default.aspx?View=Login (the login.ascx)
I also created a SecureUserControl class and put it into the Infrastructure folder. I derived UserControls like Orders.ascx from this new base class, providing me with the Forms Authentication mechanism. All other controls, like ProductsList, ProductDetails derived from the standard UserControl.

Creating the Notion

Once you have this all done, you will have two distinct folders containing two distinct 'ideas/notion', infrastructure and extensible. These two ideas are important to a framework.

Next, change the Namespaces for the files so that they make more sense to what we are trying to do. As an example, I named the Login, MyAppNamespace.Infrastructure.Authentication.Login and ProductList MyAppNamespace.Extensible.ProductList

Making it Extensible

The next step is to make the elements that we deemed as Extensible, more appropriate for extensibility.
As an example, the ProductDetails UserControl currently shows the details in a set way. For this we should separate the UserControl into two Types.

  • Add a new Class to the Extensible folder.
  • Copy the code from the ProductDetails code behind into the new class (overwriting the template class code)
  • Rename the class to ProductDetailsBase
  • Change all the protected members at the top of the class (the variables for the UI controls) to public
  • In the code-behind for the ProductDetails.ascx UserControl, change the inherited Type from UserControl to ProductPageBase

  • Comment out the code in the load event

    Comment out all the protected members
This is not yet complete, but it will run (if it was done correctly). The public members of ProductDetailsBase are instantiated by ASP.NET as it would have in the standard code-behind.

This is not ideal, as the User would have to have created the controls on the ProductDetails.ascx with the same name. We need to change this.


The next step, is to create Properties on ProductDetailsBase for the relevant data for the UI, such as UnitCost, ModelNumber etc.
Then change the public members to private, and use these variables as the internal fields for the properties.
private System.Web.UI.WebControls.Label _UnitCost;

public System.Web.UI.WebControls.Label UnitCost
{
    get
    {
        return _UnitCost;
    }
    set
    {
        _UnitCost = value;
    }
}

Next, in the ProductDetails code-behind, add code the Load event to hook it all up.
private void Page_Load(object sender, System.EventArgs e)
{
    base.UnitCost = this.UnitCost;
        //set the base properties to the Control equivalent
}

You will now have noticed that the protected members we commented out, is now back again, generated by VS.NET.
Remove the commented version of the control variables.
At this point, you have a distinction between the User Interface, the names of the controls on the ProductDetails.ascx page, and the code that sets the values for these controls. You can move the controls around, or create a new ProductDetailsEx version that derives from ProductDetailsBase and the 'base' functionality remains.

Easy To properly demonstrate this, create a different ProductsDetails page, that has a different layout, but derives from the ProductDetailsBase.
Once you have done this for all the UserControls in the Extensible directory, you will have the first glimpse of the Framework to be.

The next step

Whats next?

Here is a small list of next plausible steps:
  • Separate the project into two (Framework and Application)
  • All base classes, Infrastructure remain in the Framework
  • Within the Extensible directory we split the usecontrols into the UI and the base class , therefore we can move the UI elements into new project. This is the Application that uses the framework
  • Create some custom tags in web.config for settings ie. Which implementation of ProductDetails should be loaded and add the logic to the PageController Pattern
  • Think about tiers, layers and further refactor the application
  • Build two simple applications (preferably very different products) using the framework, and extend the Framework as required.



Building Frameworks Tip 1 | Tip 2 | Tip 3 | Tip 4 | Tip 5 |



Read: Building Frameworks Tip 6

Topic: Attributes that take parameterinfo or methodinfo Previous Topic   Next Topic Topic: Review of BizTalk Unleashed by Susie Adams, et al

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use