At work, we have a way of registering ASP.NET controls to be secured based on the current user's application role. Securing the controls happens in the PreRender event of the MasterPage of the application. For a while, it seemed to work pretty good. Then we noticed an important bug: if we registered a control inside a TemplateField of a GridView, the control would lose its security settings when a user clicked on one of the column headers to sort the grid. For instance, if we registered an ImageButton that would delete the current row to be secured, and the current user's role implied that the delete image should not be shown, the image would in fact be invisible. But when the user changes the sorting of the grid, all of a sudden the user can see the image.
I was the lucky one who got to fix the bug. First of all, i want to make it clear that i'm definitely not an experienced ASP.NET developer (i usually try to stay away from the presentation layer). Anyway, after a lot of debugging, i figured out that the GridView's postback events were handled after the PreRender event of the MasterPage was handled. When clicking on a GridView's column headers when sorting is enabled, the control performs a new DataBind. When looking at the source code of the GridView through Reflector, it shows that DataBind deletes the existing child controls and then recreates the new ones. Bingo! Our code set the control to be invisible, and after that, the GridView simply deletes its child controls and recreates it, thereby making our ImageButton visible again.
That took me about 5 hours to figure out. An experienced ASP.NET developer probably would've figured this out much more quickly or even would've avoided the issue by securing the control in a later stage of the page's lifecycle. Anyway, i fixed the bug by assigning a delegate to the PreRender event of each control that had to be secured, and then simply set the correct settings for the control at that time. It didn't feel like a good fix, but i couldn't find anything better at that time. So today i figured i'd play around with that issue at home, and it turns out the solution is actually much simpler and cleaner than what i did at work. The best way is to simply secure the controls in the OnPreRenderComplete method of the Page. This way you're sure that your code is executed after each control has finished its lifecycle. So you can simply hide or disable controls during the OnPreRenderComplete method of the page without worrying that the controls will be destroyed and created again. If you must secure the controls in the MasterPage instead of the Page itself for whatever reason, it's best to simply assign a delegate to the content page's PreRenderComplete event during the MasterPage's Page_Load() method and then secure the content page's controls in the event handler.