November 2005 Entries

For several days,  I have struggled with a problem with the view state on dynamically loaded controls.   I am using a fair number of dynamic controls on a little project that I have been working.   Everything was working fine except in one section.    In this one section,  view state was not being tracked until after the first post back.   Events were not responding until after the first post back.    Everything seemed to be setup properly and it was working everywhere else.   

Very perplexing.    Who ever heard of a problem fixing itself like that?    I have heard of dynamic controls NOT working after the second post back.    This was really strange.   Here I had obviously made some mistake in wiring up the dynamic controls that fixes itself after one post back.

I tried every thing I could think of to track this down.    I overrode the LoadViewState method, PreRender, SaveViewState, UnLoad, etc.    Everything looked good.   Everything was behaving as expected after the initial post back.      As hard as I looked,  I couldn't see anything different between the sections that worked and the area that was misbehaving.    A fresh set of eyes was needed.

Sometimes you can be too close to a situation to see what is in front of you.

I knew that it was important that the dynamic controls get the same ID when they are reloaded as they had when initially added.   I took great pains to reload each control in the same order.    I took great pains to unload controls that were no longer needed before adding any additional controls.    What I failed to notice and only a fresh set of eyes could see was that  in one place, coincidently the place having problems,  I incremented the control count,  added the control to the containing control's control array, and finally set its ID, using the control count.   Everywhere else,  I incremented the control count as the last step.  

This means that for the problematic section, there would be no control 0 when the controls are originally loaded.   Because I was incrementing the control count before using it, the first control would always have an ID of 1.   On post back when I reloaded the dynamic controls, the control would load but be given an ID of 0 because I was using the control count and then setting it.   There was no viewstate for Control 0 and there was no longer a control for the viewstate data associated with the control with ID of 1.    After the first post back, the gap in the control ids was removed and from then on everything worked properly.

I hope that my struggles help someone else.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

There is no greater joy, no finer ecstasy than solving a perplexing problem.    The more perplexing, the greater the euphoria. 

In many ways, I live for this rush.

Often the release that comes from the resolution of such problems makes up for the embarrassment when the root of the problem turns out to be a simple mistake.

 

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Have you ever been struck with a table design that did not work well for what you now needed?    Sure, we all have.

One common scenario is to have a table where all of the data that you need is in multiple records, but you need it returned in a single record.

A common solution is to join the table to itself multiple times.    Depending on the size of the table, this might work.   Sadly this approach does not scale well.

A more scalable solution would be to use grouping logic to get all of the data in a single pass.

Suppose you have a table that totals sales data monthly, but you need to display multiple months side by side.

Here is the table

ReportingDate Volume
06/01/05 25000
07/01/05 18000
08/01/05 27000
09/01/05 32000
10/01/05 30000

If you wanted to produce a record set that looks like this:

 

June July August September October
25000 18000 27000 32000 30000

You could do something like this:


select JuneData.Volume as June, JulyData.Volume as July, 
       AugustData.Volume as August, 
       SeptemberData as September,
       OctoberData.Volume as October
from   SalesData JuneData, 
       SalesData JulyData, 
       SalesData AugustData, 
       SalesData SeptemberData, 
       SalesData OctoberData
where  JuneData.ReportingDate = '06/01/05' and 
       JulyData.ReportingDate = '07/01/05' and
       AugustData.ReportingDate = '08/01/05' and
       SeptemberData.ReportingDate = '09/01/05' and
       OctoberData.ReportingDate = '10/01/05'

 

This works well for small tables, but if the table in question is large, this doesn't work so good.   Instead I prefer to do something similar to this:



select max (case reportingdate when '06/01/05' then volume 
           else null end) as June,
       max (case reportingdate when '07/01/05' then volume 
           else null end) as July,
       max (case reportingdate when '08/01/05' then volume 
           else null end) as August,
       max (case reportingdate when '09/01/05' then volume 
           else null end) as September,
       max (case reportingdate when '10/01/05' then volume 
           else null end) as October
from   SalesData

You could then add any additional filters you need like region restrictions, product restrictions, etc.

You get the same results as the earlier query, but with better scalability.

Once you get comfortable with this pattern, you'll be surprised at how often you can use it.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Earlier I posted about my car being stolen.   Things have settled down a little.

The police found my car.    Someone on the other city of the city saw someone ditch my car and steal another one.    That person called the police and they recovered the car.   They recovered it two days before the insurance was going to settle.

Once the car was recovered, it was in the body shop for 4 weeks.   Whoever stole it did about $5,000 worth of damage.   Additionally, insurance had to pay out $900 for a rental car.

Nothing like an ordeal like this to bring out the paranoia.   It was several weeks before I could sleep through the night without having to get up and look outside.   I have also gotten very picky about what I leave in the car at night.   On the plus side, the car stays cleaner.

There was substantial body damage done.   No mechanical damage.   In all reality, the car is as good as new, but something still doesn't feel right.   Even after all of the damage was repaired, there is still a lingering sense of violation.    That may never go away.

I seriously thought about getting one of the new hybrids.    I seriously thought about getting several different cars.    I couldn't decide on one.  Plus by the time the car was fixed, hybrids were in short supply.

 

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Recently I was asked what it is that a software architect does.   This is a difficult question to answer.    We do so much.     For the outsider it can difficult to explain.

I started thinking about it in terms of the balls that we juggle.   Here is my initial list.   I am sure that there are more:

  • Performance
  • Maintainability
  • Security
  • Reliability
  • Scalability
  • Look and Feel
  • Flexibility
  • Best Practices
  • Time lines
  • Politics   (Office and Project)
  • Software Version Upgrades
  • Individual egos
  • Scope Creep
  • System Integrity
  • System Integration
  • Budget
  • Deployment
  • System Conversion
  • Training / Mentoring
  • Hardware / Network Constraints
  • Business Requirements

In future posts,  I will ruminate over my personal experience in some of these areas.   I hope to hear what others are or have experienced.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

I have been thinking recently about the various architecture / abstraction layers that would be useful in making up an Enterprise framework.

The goals would be to improve consistency, decrease time to market, improve quality, and simplify the development and testing efforts in general.   Pretty lofty goals, but important none the less.

The layers that I have in mind include (in no particular order):

  • Security Abstraction Layer
  • Validation Abstraction Layer
  • Conversion Abstraction Layer
  • Data Access Abstraction Layer
  • Work flow Abstraction Layer
  • Web UI Behavior Abstraction Layer
  • Web Service Facade Layer
  • Business Entity Foundation Layer
  • Caching Abstraction Layer
  • Configuration Abstraction Layer
  • Exception Management Abstraction Layer
  • Instrumentation Abstraction Layer

Many of these will be adapters to the Enterprise Library.    This is important because the Enterprise Library is not guaranteed to be compatible across various versions.    Build your apps against your adapter layers. If future version of the Enterprise Library are incompatible, you only have to change the adapter and not every application that you have written.

Some of these other layers are niceties that the Enterprise Library might include one day.    If they do, you can hopefully adapt your abstraction layer to use it.   If these never get include in the Enterprise Library, they will sill be useful layers on their own.

Hopefully, as these layers emerge, they will follow the same ideals as the Enterprise Library itself.   Specifically,  consistency, extensibility, ease of use, and integration.

In future posts, I hope to tackle each of these layers and discuss my thoughts on what should go into each of them.   I welcome any feedback from anyone going through similar exercise.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

I recently say a couple of articles on CodeProject that showcased wrappers to simplify using the CodeDom

http://www.codeproject.com/csharp/CodeDomPatterns.asp

http://www.codeproject.com/csharp/refly.asp

I am in favor of anything that encourages use of CodeDom and tries to flatten the learning curve for using the CodeDom.

Unfortunately, most examples of using the CodeDom seem a little contrived.    This makes using the CodeDom seem like over kill.

Consider some of the following applications:

  • Using the CodeDom to pro grammatically generate proxy methods for binding parameters to stored procedures
  • Using the CodeDom to generate web services for all of the methods in a specified class
  • Using the CodeDom to generate code to exercise class libraries by calling every method in the class.

Some advantages of such an approach includes:

  • Rich object model makes it easy to structure code generation code.   
  • As best practices evolve, generated code is easier to maintain.   Instead of having to change every web service when a new WSE is available, you only have to modify the generator and then regenerate all of your code.   This is much better than having to rewrite every web service.
  • Code generated through CodeDom can be rendered as any language that has a CodeProvider.    This helps ensure that you will continue to get retrains on your investment in building a generator.
  • As new versions of the framework are released,  Microsoft will update the implementations of the CodeDom objects to properly support the new version.   Code generators that you write will continue to work with new versions of the framework.

There are a couple of things to also keep in mind with maintaining generated code.   Never modify generated code.    You want to protect your ability to regenerate as needed.   Partial classes in version 2.0 of the framework make this easy.    Make any customizations in a separate file and then you can easily regenerate the original file without loosing your changes.  

In any version of the framework, you can also use inheritance to protect the generation layer.    Generate you code and make any code changes in a class derived from the generated class.   Not being able to regenerate generated code makes people scared of using code generators.     Good object oriented design solves this problem.     Code generation does not necessarily lead to bad object oriented design.   

Many people frown on the use of code generators because they often produce “ugly“ code, lead to bad object oriented design, or it is unmaintainable.    I believe that using the CodeDom avoids these pitfalls and effective use requires good object oriented design rather than precluding it.

Is anyone else using the CodeDom?  

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Through much trial and error and research on the web, I have come up with the guidelines for dealing with dynamically loaded controls.

  • Load the controls in the same order on each post back
  • Add new controls to the Controls array before setting any properties.    Properties set before the control is added to the control array will not be tracked in View State.
  • If an event handled after dynamic controls are added causes diferent controls to be loaded, the newly reloaded controls may need to be explicitely unloaded.    
    • For example, if a page has dynamic controls added based on the month selected, when the user selects a different month, the existing controls will need to be unloaded before the new controls are added.
    • When removing the dynamic controls, start at the end of the list and work your way backward.
  • Rewire any event handlers as soon as the control is reloaded on each post back.

I found the following articles very helpful:

http://clariusconsulting.net/blogs/vga/archive/2003/08/11/66.aspx   Dispells the myths about when to reload dynamic controls

http://scottonwriting.net/sowblog/posts/2129.aspx   Clears up some misconceptions that I had about viewstate.    Points out the importance of adding the control to the controls array before setting any properties.  

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Here are some guidelines that I have started following to structure pages and get the style sheets right.

I have found it useful to have one style sheet for the web site that sets the color schemes, fonts, and page structure as well as any other UI constraints that would be common across all pages in the site.   I then add a new style sheet for each page to handle positioning information specific to that page.   This seems to keep the style sheets more manageable while still keeping the content separate from the format and positioning.

When designing a page, I have started following the following process:

  1. Mark up the page with HTML using simple input tags to get the flow and style sheets right.
  2. Convert the HTML to an aspx or ascx as appropriate.
  3. Convert the input tags to server controls using the same style classes as the original HTML
  4. Wire up the data binding
  5. Wire up the navigational controls
  6. Replace built in controls with third party controls as appropriate.

This first step could potentially be done by a designer allowing developers to skip this step all together.   

Having the original HTML to refer back to as a reference also comes in handy.   At every point, we can refer back to it to ensure that you are still true to the original design.  

Is anyone following a similar approach?   Does anyone see any concerns with such an approach?

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

I found this great presentation covering how to structure a style sheet.     steps through various details such as fluid layout, structuring containers, cross browser style sheet support, font scaling, and behaviour within form elements.

A great dal of very useful information very well structured and written.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati