May 2003 - Posts

New LoadFinished event for Page

Note: this entry has moved.

Lots of people starting to learn ASP.NET tend to heavily depend on the Load event. They find quite naturally to write most core logic into Load until they realize their code just doesn’t work as expected and start coding all kind of hacks.

 

A common example of this mistake is to write code in Load that depends on values that will be updated only after postback data has been processed; but as Load fires before postback data (2nd try) and RaiseChangedEvents and RaisePostBackEvent are processed such code won’t work properly -- and that is when people start writing hacks like peeking at the Forms collection to get the updated value; the WebForm model is not followed and bad things happen when you do that J

 

If you still doesn’t get the scenario I’m talking about take a look at this post.

 

The solution to this? Move your code to PreRender, sure; but this doesn’t sound very intuitive to a beginner.

 

I believe that adding a brand new event to Page, something like LoadFinished that fires right after 2nd try postback data and changed & postback events are processed and right before PreRender would be a more natural choice where to put such code.

 

You could then market this new event as the one that fires when the page has completely finished its loading and the place where any code can safely depend on all postback data to be updated.

 

 

Posted by vga with 7 comment(s)

WebMatrix is beating VS.NET...

Note: this entry has moved.

I just come across this screenshot of the next drop for WebMatrix in NikhilKo’s blog.

 

WebMatrix is now supporting one *very* requested wish of VS.NET users… better design-time support for Web User Controls. Yes… instead of getting that little ugly-and-awkward gray box you now get WYSIWYG.

 

Sincerely, I’ve never considered WebMatrix very seriously. I’ve often referred to it as a toy or as a “kind-of-FrontPage”; (I mean, who can live without intellisense? J) but it seems like the next drop will make me change my mind, at least a bit.

 

I’m asking myself: “When will we, VS.NET users, get decent design-time support for UC?”

 

Me: “Whidbey?”

 

Me again: “Surely. But that seems *so* far away.”

 

Moreover, that question leads me to another one:

 

“What cool new feature -not implemented by VS.NET- will be WebMatrix implementing at the time VS.NET catches up with UC?”

 

Posted by vga with 5 comment(s)
Filed under:

Extending Master Pages

Note: this entry has moved.

During last March I was writing a chapter for a soon to be released Wrox Professional book on Advanced ASP.NET. As you may already know, Wrox is gone by now, so my chapter (and the whole book) never made it to the public L

 

During that time (late-night time…) I wrote an entire chapter about Page Templates/Visual Inheritance/YourFavoriteNameGoesHere in ASP.NET. I ended up with a 50 pages chapter with more of its content dedicated exclusively to the Master Pages technique (coded by Microsoft’s David Ebbo) and how to extend it.

 

Although Master Pages was just a quick sample that David put together to demo a basic concept, it is, in my opinion, the best way to go if you’re looking to implement page templates in your ASP.NET application. But, as with any quickly put together sample, it leaves some room for improvement and fixes. I will summarize a couple of them here hoping that if you’re actually using Master Pages or considering using it you could benefit by knowing about them.

 

NOTE: if you’re not familiar enough with Master Pages or any other template technique, I recommend you to take a look at fellow MVP Paul Wilson’s articles on the subject before continuing this reading.

 

You’re already familiar? Ok then… read on J

 

Better integration with the ASP.NET parser

 

This means moving some code from Control.AddParsedSubObject to a ControlBuilder for executing code only once at parsing time. There is also room for adding a couple of new checking’s (i.e. enforcing attributes to be set).

 

Couple of fixes

 

Let’s take a look at the following fragment for ContentContainer.OnInit:

 

protected override void OnInit(EventArgs e) {

   if (MasterPageFile == null)

      throw new Exception("You need to set the MasterPageFile property");

 

   // Load the master page

   Control masterPage = Page.LoadControl(MasterPageFile);

 

   foreach (Content content in _contents) {

      // Look for a region with the same ID as the content control

      Control region = masterPage.FindControl(content.ID);

      if (region == null) {

           throw new Exception("Could not find matching region for content with ID '" + content.ID + "'");

      }

.

.

.

}

 

There are two main pitfalls (marked in bold) to watch out for in the above code:

 

1.        As you already know the Control.FindControl method when called with a simply ID will search into the current naming container for the specified control; this will break when your Region controls are contained in a different naming container than the usercontrol itself, i.e:

<owc:Region runat=”server” id=”one” />

<owc:MyOwnNamingContainer runat=”server”>

     <owc:Region runat=”server” id=”two” />

</owc:MyOwnNamingContainer runat=”server”>

<owc:Region runat=”server” id=”three” />

 

2.        Checking against region == null it’s not enough to guarantee correct usage of Master Pages. For example it could happen that a page developer while creating a new page specified a Content control with an ID that has no correspondent Region control but matches some other control type; needless to say the check won’t fail and we’ll be in trouble. So we should be checking region against null plus that it is an instance of a Region type.

 

Support for inheritance between templates

 

This is by far the most powerful feature I’ve added to Master Pages. There is some real power (code reuse, simplified maintenance, etc) you could benefit from when being able to inherit between templates. The code to add this feature is quite straightforward, basically a modified ContentContainer that is aware of inheritance and a couple of support methods to walk the inheritance chain and setup Region controls appropriately.

 

Master Pages as an application-level feature

 

Coding a config section for Master Pages that you could use to easily setup it for your particular web application is definitively useful. With settable attributes like BaseUrl that would allow you to easily change the location where to look for templates.

 

VS.NET integration

 

Due to the fact that the page parser is currently not extensible, it is required that you manually add some repetitive declarations to any page that uses templates and also to your templates files. This tends to be a really boring and repetitive (did I already mentioned that?) task. I’ve tackled this by coding a couple of VS.NET wizards and templates (VS.NET templates this time!) that create the necessary skeleton code thus saving you from boring and rep… typing.

 

Other features I’ve coded are support for: I18N, design-time, programmatically handling Master Pages and something else I can’t remember right now J… I could address these features in a future post if there is enough interest in them.

 

Posted by vga with 7 comment(s)
Filed under:

When NOT to choose composition: an ASP.NET forums example

Note: this entry has moved.

Most people starting to develop custom controls have problems figuring out when to go with a full-blown composite control and when to go with a rendering approach. It may take some time until you fully realize the pros & cons of each approach.

 

It happens that I found a composite control in the ASP.NET Forums application that is a great example on when NOT to code a composite control. Don’t take me wrong. The ASP.NET Forums application is a great application, with lots of useful features and more to come. It’s just the fact its source code is influencing so many beginners that lead me to believe that such control is not serving as a good example.

 

The culprit is the AlphaPicker control. In case you don’t know it already, it’s a very simple control whose purpose is to display A to Z letters plus an “All” entry as links to ease navigation. Let’s take a look at its CreateChildControls method:

 

protected override void CreateChildControls()

{

     Label label;

     // Add the series of linkbuttons

     char chrStart = 'A';

     char chrStop = 'Z';

     // Loop through all the characters

     for (int iLoop = chrStart; iLoop <= chrStop; iLoop++)

     {

          Controls.Add(CreateLetteredLinkButton(((char) iLoop).ToString()));

          label = new Label();

          label.CssClass = "normalTextSmallBold";

          label.Text = " | ";

          Controls.Add(label);

     }

     Controls.Add(CreateLetteredLinkButton("All"));

}

 

Notice how two child controls get created for every letter; a LinkButton (through CreateLetteredLinkButton) and a Label with the “ | “ text serving as a letter separator. Also one more LinkButton is created for the “All” entry. This causes the simple AlphaPicker control to end up having 53 child controls. No, it’s not a typo. Fifty-three full-blown controls, that must be created, initialized, consume memory, etc.

 

Due to AlphaPicker extremely simple nature, you could code exactly the same control without the need to create a single child control -- just using rendering.

 

I made a post about a year ago in the ASP.NET Forums regarding this same topic and received a response from the guy in charge of the source code (can’t provide a link to it as the search is not working right now), he accepted the comments and told me he will be considering rewriting the control. A year later, AlphaPicker remains untouched, but hey!... it’s never too late! J

Posted by vga with 2 comment(s)
Filed under:

Inside the new ValidateRequest feature, part II

Note: this entry has moved.

I received a couple of questions by private emails regarding my previous post about ValidateRequest. I believe it may be useful to post them (and the answers!) thus saving me from receiving the same question again J

 

Q: At which point does the framework call HttpRequest.ValidateInput (if it does so) to force validation on subsequent access to the collections?

A: Yes the fx will call HttpRequest.ValidateInput. This is done by the page parser when generating a new class based on the .aspx file; it overrides the TemplateControl.FrameworkInitialize method to add a call to HttpRequest.ValidateInput (along with other initialization code that exists since the 1.0 bits), i.e.:

 

[C#]

protected override void FrameworkInitialize()
{

     // other init code goes here

     this.Request.ValidateInput();
}

 

 

Q: Is a collection validated every time it is accessed? Is some caching being done to avoid this?

A: No. Any of the three guarded collections (Cookies, Form, QueryString) will be validated just once. After a collection passes validation, the correspondent bit flag indicating that validation is required (which was previously set by HttpRequest.ValidateInput) is cleared. Further accesses just return the collection without any validation.

 

Q: Can I force request validation to happen from inside my custom control no matter what value the page developer has set the ValidateRequest attribute to?

A: I believe the best you can do in this case is to call HttpRequest.ValidateInput as soon as possible from your custom control code, for example in your class ctor. This should enforce validation before any event handler coded by the page developer runs. Of course, the ctor for any other control which is located above yours in the control tree hierarchy could actually access these collections without any validation.

 

Posted by vga with no comments

Spreading the custom controls love

Note: this entry has moved.

Last Wednesday Microsoft Argentina organized the MSDN Briefing, a big event, that was attended by more than 1000 local developers. They asked me to do a presentation about advanced ASP.NET programming. I wanted to talk about development of advanced custom controls (i.e. templating, databinding, complex designer support, etc) but I was not sure about the current number of developers that were doing this kind of stuff that may be interested in the talk. So risking myself to having just a few (or zero) attendees I decided to go with it anyway.

To my surprise it was one of the most attended talks (surpassing other “favourites” talks like the webservices one). During the two-hour talk I received lots of questions and a few complains (hey! I’m not from Microsoft! You should complain to them! J).

The questions were mainly basic ones; none of them were actually implementing complex designer stuff or developing controls that supported either templates or databinding. Just a few ones were actually beginning to explore these topics.

On the complain side, documentation (poor documentation, that is) was #1 by far. I told them I agreed with them, but I’m not sure if they really believed me (maybe it was the MS t-shirt that I received for the event…).

I brought with me NikhilKo’s book to recommend it. Almost none of them did know about it; I would imagine this is thanks to Microsoft Press (inexistent) presence outside of the states.

To summarize, it was great to met lots of developers working on such stuff and I just hoped that I helped to spread the custom controls love a bit… J

Posted by vga with 1 comment(s)
Filed under:

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

 

Posted by vga with no comments

Inside the new ValidateRequest feature

Note: this entry has moved.

I think that one of the most misunderstood features in ASP.NET 1.1 is the new Request Validation for preventing script attacks. I’m starting to see various posts in the Microsoft public newsgroups asking for help on this, flaming the feature, etc; most of them are just based on a misconception on how this feature works. Moreover, last week I made a presentation (many thanks go to rhoward for sending me his ppt!) introducing ASP.NET 1.1 to a group of about 150 folks at Microsoft Argentina and again I confirmed lots of confusion about this new feature.

 

I’m not going to repeat here what is already written in the docs or in additional articles. Also I believe that looking at this picture will help understand the following text.

 

This new feature is implemented by new methods added to the existing System.Web.HttpRequest type plus a new helper type named System.Web.CrossSiteScriptingValidation.

 

In HttpRequest, the get accesors for properties QueryString, Form and Cookies had been modified to check for dangerous content in the items of the collections they are wrapping before returning them. This new behaviour is only active if ValidateRequest is set to true (either at the Page or application-level; note that true is the default value). If you explicitly set ValidateRequest to false no validation will occur.

 

There are two new methods for validating the previously mentioned collections: ValidateNameValueCollection and ValidateCookieCollection. Why two different methods? Because the types of items to be validated are quite different and may require special handling. Let’s see this in detail:

 

ValidateNameValueCollection validates the items of a NameValueCollection, which is a collection that stores name/value string pairs, i.e.:

 

Name/Key

Value

FirstName

Catalina

CustCode

532

__VIEWSTATE

dDwtMTI3OTMzNDM4NDs7Pn2S7p

 

 

This method will check the Value string for each item but __VIEWSTATE as there is no sense in checking it for dangerous content.

 

ValidateCookiesCollection validates the items of an HttpCookieCollection, which is a collection of HttpCookie objects. The HttpCookie type has quite a bit more information than the simple name/value pair that we previously saw; it has properties like: Expires, Domain, Path, Value, Secure, etc. Like the previous one, this method is only interested in the Value property of the stored items. In this method there is no special handling of items like the __VIEWSTATE case shown above, every item in the collection is checked.

 

Both Validate* methods don’t contain any validation logic coded into them; they just loop through the items in a collection calling the ValidateString method and passing to it each item’s value as an argument. ValidateString still doesn’t implement any validation logic by itself; it uses a new private helper type named System.Web.CrossSiteScriptingValidation (yes, I said private, so forget about extending the validation logic) that has a couple of methods who check for different kind of dangerous content. How this CrossSiteScriptingValidation type looks like? It has four private static methods with very self describing names (IsAtoZ, IsDangerousExpressionString, etc) that perform the actual validation work and it exposes an internal static method named IsDangerousString that is called by the HttpRequest.ValidateString method previously mentioned.

 

The forgotten collections

 

As far as I can tell there seems to be no checking against the Headers and ServerVariables collections. I agree these are not so ‘popular’ as the previous three, but if the attempt was to offer maximum security right out of the box I don’t know why they’ve been excluded. Anyway, it should be great to hear some ‘official’ comments on this J

 

Documentation and cosmetic VS.NET bugs

 

Lastly, there is one new public method HttpRequest.ValidateInput that the docs describe as: “Validates data submitted by a client browser and raises an exception if potentially dangerous data is present”. This phrasing has already caused some confusion on the public newsgroups. Most people expect this method to perform the validation logic and to raise an exception if dangerous data is encountered (well… they’re just expecting what the docs describe). Unfortunately this is not really what this method does which is to just set three flags (one per collection) that will cause validation to happen later when any of the collections are accessed. Because of this, people write code like:

 

[C#]

try

{

     HttpRequest.ValidateInput();
}

catch(HttpRequestValidationException e)

{

     // handle an HttpRequestValidationException
     // that will never be thrown by the code in the try block

}

 

While still at the Bugs Dpt., it seems like VS.NET 2003 has not catch up with this new feature; when a page is selected the Properties window doesn’t shows a ValidateRequest property that would map to the ValidateRequest attribute of the @Page directive (as it actually does with other properties like Trace, Culture, etc.)

 

 

Posted by vga with 13 comment(s)
Filed under:
More Posts