The quest for a questionaire web control

Lately, I was struck by a new interesting idea of building a .Net Project. This actually comes from a discussion with my Manager about what to do at the end of the project that we are currently working on. He talked about wanting to make a questionaire or a survey for the post-mortem. He then told me about how he will have someone make simple questionaire with his predefined set of questions and hosted it in one of our internal servers. The service will be much a cgi based. But what goes inside my head was different. Instead of a static questionaire, I thought I wanted to make a dynamic questionaire. In addition to that, I want to componantized this questionaire so that people who will use it just need to drop the control, set up their data and feed it to the questionaire control. Pretty simple heh, boy how I was wrong… But lets just get to what I have done and found out today.

As usual, I always drew designs before I started programming. This process actually took me around 3-4 hours. And in this design phase I quickly identified problems. Given my experience with ASP.Net, I know that controls automatically can handle postbacks and set their values or state to a correct value. That is, if the controls are static. But what about if the controls are dynamic? Well, as long as you reproduce exactly the controls then it wont be a problem. But what if you cant? The problem with questionaires is that you may have lots of questions that can span to multiple pages. AND, because this is general control, it means no statically defined pages or control tree (unlike the cross page posting where you can refer to the previous page in strongly typed manner). Some browsing in the internet for this problem reveals a solution, it is to rebuild the control tree and then redirect. Another solution is to use java script which will call a special method that will update your data. None of this is what I really wanted to do. For the first one, it seems terribly stupid and I have doubts that you can cleanup your controls after the Page Load event is over. It looks like a hack and I wanted to find another way for doing things. THe second one, means I have to build a special service for that and that is high coupling and have to be done outside of the control border. Another reason is that it is completely relies on client browser doing the right thing. I want to avoid browser compatibility issues as possible.

So thats the dilemma, after a while of thinking, I thought on an idea of actually dealing with posted data manually. If we can make the key value of the posted data predictable, actually we can just tapped in the postback data and mapped them to the entities. The key for this scheme is the Id. This Id have to be unique and can be mapped back to the entity in question. An important note to remember is that even though I said it should be able to map back to the entity, but I realized that is not a good idea from security point of view. What if a hacker manually created his posted data and modify the id to modify some other question? So here is my scheme for this Id:

Client            |          QControl          |   Entity
------ Id ---->   |  Reconcile  <-- Predict Id | <-- Id ----


With that out of the way, my plan is to build a simple questionaire first that only consist of Labels and Textboxes, and all the layers that is needed to support it (means building entities that the web questionaire control can understand). Very simple, very straight-forward. The web control to request the list of these predefined entities and build controls that will reflect them.

public class entity {
public String Id;
public String Question;
public String Answer;

Now, the questionaire control can automatically build the controls that will represent those entities. The first question is when to build the controls. ASP.Net Page triggers events to indicate the position in the lifecycle where they are at. Now, we can trap these events and build our controls right there. However, then our control will be tied to the Page and that will make the control unusable. What we need is something more fundamental.

As I mentioned before, I am trying to build a control, and as all controls in ASP.Net is derived from Controls (or its derivatives of WebControl or CompositeControl). I started by deriving my control from WebControl.

public class WebQuestionaire : WebControl

From there, I went forward on creating dummy data so that the control available in the designer preview window and so that I dont have to worry about the data at this stage. The implementation of the control building was pretty straight forward.

protected override void CreateChildControls ();

This method actually handles the control building that ASP.Net will call on creation of the control. Why not build this in the Questionaire control? Some of the things that I noticed if you do that in the constructor, then the base control tree within the page itself was not ready yet. Other than that, properties in the control itself was not been set and will have the value of Null. THe Page property have null because the control is not being created yet. So, instead of having to handle that pain, just do something simple to initialize the control itself and let ASP.Net request for child control creation when the time is right. Now, why do I need access to Page control. It is to get to the main Form property where the postback data will be available. Another advantage with waiting the creation of the child controls is that I can get the definite control id for building my unique ids.

In order for building a recognizable id, I have to account for duplicates. This can be handled by having the Questionaire control be marked by INamingContainer:

public class WebQuestionaire : WebControl, INamingContainer

All child controls of this control now will have the control id prefixed on the front which will eliminate the duplicate problem. Also, we can get this id programatically by using the UniqueId property or the ClientId property (for their differences refer to MSDN).

Now, I can create the controls, I can create the unique Ids, I know that this is best being created using the CreateChildControl method. BUt what about the Id reconciliation what is the best place for placing this? I am not sure if this is the best way, but right now what I did is I hijacked the events. Controls actually expose some event trigger methods that can be overriden such as OnInit, OnLoad, etc. What I did, I override the OnLoad (maybe I can do it using OnInit also, but I fear the controls not being initialized properly if I mess around with it. But let me try that another time) and access the Page.Form to access the postback-ed data and run my reconciliation method there. And it worked fine. So now, I have a working protoype on the Web Questionaire Control.

I realize there are some points that need to be researched more before I can go further. So, right now Im going to reanalyze things and weighs my options.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: