DCSIMG
How to divide page into user controls as quietly as possible? - Ran Wahle's blog

Ran Wahle's blog

How to divide page into user controls as quietly as possible?

Post by my friend and colleague Gil Fink, has reveled one of the difficulties of our project.
A legacy system, poorly designed and implemented and our need of rewriting some of
it's code in order to make it easier for us to extent it with more features as demanded
by our users.

Another aspect of our legacy system was pages with lots of controls, almost each and every
one of them has server-side event (click, textChanged, selectedIndexChanded, etc.) while
best practice is to divide the page into units of User Controls while the page acts as a router
between them and between them and the business layer.

 

So, How can we change the existing situation to be closer to the desired one?
Here we have a long and risky process, I'll try and  give it's details:

 

"Before you begin" stage

1. Make the time to work on it. It is long process and you can fall into many
   holes along the way. If you have the time to work on it continuously it's you
   can proceed, if  not - ask for the time. If it is very much needed, you'll be given
   the time to do so.

"Begin" stage

2. Cut all markup belongs to the user control which you need to divide into a new
    User control. Do not transfer any code-behind at this stage! Put the new
   User control inside the page where the transferred markup used to be.

Compilation Errors correction stages

3. look at all compilation errors. Courtesy of VS2008 SP 1 you'll see it all without
    compiling, given that your changed page is open. The compilation errors  will
    mostly be the absence of the controls transferred to the new user control.
    For each control being transferred, make a property represents it's data . By all
   means, do not expose any inner control as public property
. Here you can also
   change the data type (which is string most of the time, to the type needed ,
   and put all parsing code inside the property).
   After doing so, whenever the page's code behind takes data you can replace
   the controls by the user control's data properties you've created.
   Note - this should be done with caution because data type changing are risky
  

4. There are still compilation errors, these errors refers to the control's state, style
   etc. Here you have no choice but to move this code to the user control.
   Make small methods in the user control, corresponding to the methods on
   the page's code behind, transfer the lines referring to the internal controls
   and call these methods from the original methods.
   For example : if you have a method call SetUIState containing lines referring
   to the inner control,make a public or an internal method inside the user
   control, call it SetUIState, transfer the relevant lines into it and call it
   from the original method.

Runtime exceptions correcting stages

5. By now, all compilation errors should be corrected, however our control
    won't work mainly because it doesn't contains the event handlers to
    handle it's inner controls evens. Therefore we do the following:
    For each event of the inner control we make public event of the user
    control, a protected event handler that will only invoke the event
    recently created.

6. On the page's markup we should add all events created on step 5 and
    for each event we associate  the event handler to the old event handler was
    for the inner control while being on the page. That's how we won't
    change server side behavior of our page.

Client code handling

7. Now, that all runtime exceptions should be behind us, it's time to
   handle client errors that might occur. Client errors may occur if there
   is JavaScript code referring to the control's ID hard coded, and where
   there is client scripting referring to the internal controls with server
   code islands, which will cause runtime errors.
   Here you have to do the following:
   A. Take all client code referring to the internal controls to the
        user control's markup.
   B. Whenever there is reference to the internal control ID's in client
        script, you should change it to <%=YourInternalControl.ClientID %>
        That's because whenever a control is put inside composite control
        (or user control for that meter) it changes it's ClientID.

 

Summery: This was a long post mainly because the process is long. The goal
is to gain more encapsulation and code clarity for our system without changing
it's functionality. However, this is just the first step. You soon will see
that you have a little bit clearer code and but this is only the first step
of a long journey of making it better.

kick it on DotNetKicks.com
Posted: Dec 20 2008, 10:04 PM by Ran Wahle | with 3 comment(s) |
תגים:,

Comments

DotNetKicks.com said:

You've been kicked (a good thing) - Trackback from DotNetKicks.com

# December 22, 2008 12:45 AM

Web Development Community said:

You are voted (great) - Trackback from Web Development Community

# December 22, 2008 6:10 PM
Leave a Comment

(required) 

(required) 

(optional)

(required) 


Enter the numbers above: