views:

25

answers:

1

I'm working with dynamic fields in ASP.NET due to a very specifc and rigid end-user requirement that would take 2 hours just to explain. Suffice it to say, I can't make the requirement go away.

Anyway, I have a working solution in place; no problems with controls loading, rendering or maintaining their ViewState. This is what my OnLoad looks like:

public void override OnLoad(EventArgs e){
    //don't need to check IsPostback, we have to load the controls on every POST    
 FormDefinition initialFormDefinition = ServiceLayer.GetFormDefinition(id);
 BuildControls(initialFormDefinition);
}

In order to implement some biz logic around which dynamic fields are required, disabled or optional, I need to get the posted values (i.e. the ViewState) of my dynamic controls before I can actually add them to the page control hierarchy.

It's sort of a chicken/egg problem I suppose. ASP.NET won't automagically associate ViewState with the proper dynamic control until I've added them all to the page. On the other hand, I can't add these controls to the page until my service layer has applied biz rules that hinge on their current values. I tried to get around this rather unpleasant problem by writing this bit of pseudo-code :

public void override OnLoad(EventArgs e){
 FormDefinition initialFormDefinition = ServiceLayer.GetFormDefinition(id);
 BuildControls(initialFormDefinition);
 if (IsPostBack){
  PushControlValuesIntoForm(initialFormDefinition);
  var updatedFormDefinition = ServiceLayer.ApplyBizRules(initialFormDefinition);
  ReBuildControls(updatedFormDefinition); //remove controls and re-add them
 }
}

Unfortunately, when you clear a control and re-add it, the ViewState is lost, even if the control type and ControlID are exactly the same, so this solution is a bust. Any reasonable ideas on how to accomplish what I'm after are welcome!

A: 

One way could be to load your controls and then decide if you need form definition to be be updated and if yes then re-initiate page life cycle again. See the below sample code:

public void override OnLoad(EventArgs e){

 var updatedFormDef = Context.Items["UpdatedDef"] as FormDefinition;
 if (null != updatedFormDef)
 {
    // Updated form def, rebuild controls
    BuildControls(updatedFormDef);
 } 
 else
 {
    // load initial form def
    var initialFormDefinition = ServiceLayer.GetFormDefinition(id);
    BuildControls(initialFormDefinition);
    // check whether we need to update form def
    if (IsPostBack){
       PushControlValuesIntoForm(initialFormDefinition);
       var updatedFormDefinition = ServiceLayer.ApplyBizRules(initialFormDefinition);
       if (null != updatedFormDefinition)
       {
          // we have to update UI, transfer to self
          Context.Items["UpdatedDef"] = updatedFormDefinition;
          try
          {
              Server.Transfer(this.Request.RawUrl, true);
          }
          catch(ThreadAbortException)
          {
             // Do nothing
          }
       }
 }
}
VinayC