Educating through exceptions

Note: this entry has moved.

In the public newsgroups you can read lots of posts about the Page.Register* methods not working properly. A few months back it was common to see this type of post almost once a day; today, thanks to google indexing, the number of posts regarding this issue has decreased (but surely not the number of beginners actually stumping at this scenario).

 

The problem consist of calling these Register* methods after the PreRender event. For example, a common mistake made by (beginners) custom controls developers is to write Register* calls in the Render method. This will only work for some of the Register* methods:

 

Method

Works in Render

RegisterArrayDeclaration

Yes

RegisterHiddenField

Yes

RegisterStartupScript

Yes

RegisterOnSubmitStatement

No

RegisterClientScriptBlock

No

 

So what happens when the Render method includes calls to RegisterOnSubmitStatement and/or RegisterClientScriptBlock? Just nothing (and that is the whole problem!). No script gets rendered, no error is shown. The (beginner) developer has to start guessing why his code it’s not working as expected. A quick search in google groups will give him an instant answer but I believe the framework could include a better approach to this.

 

I’m proposing to throw an exception (instead of silently falling) when any of these methods are used inappropriately. The exception should tell the user to move the code to PreRender or any other previous event. This will be even faster than searching google J.

 

I believe this could be implemented by adding proper checks in the Register* methods. When one of these methods is called, the control state for the Page should be checked and if PreRender was already processed then an exception should be thrown. Something in the lines of:

 

[C#]

public virtual void RegisterClientScriptBlock(String key, String script)

{

     if(this.ControlState == ControlState.PreRendered)

     {
          // throw an exception here

     }

     // registration continues here
}

 

I would love to see this check added to all of the Register* methods. To me, script registration should always precede rendering. But as NikhilKo (not sure if he has a blog but he wrote this great book) has properly pointed out, some of these methods (see the table above) will work even when called in Render thus changing this behaviour could be considered a breaking change.

 

For completeness sake, there is another scenario that will cause all the Register* methods to fail without giving you a clue. That happens when your page doesn’t include a server-side form; this is caused by a hard dependency between the Page and the HtmlForm classes... I will save the explanation for my next post… J

 

No Comments