Attention: We are retiring the ASP.NET Community Blogs. Learn more >

Tales from the Evil Empire

Bertrand Le Roy's blog

  • Declarative programmation will bloom with ASP.NET 2.0 auto-compilation

    You may already know that, but ASP.NET 2.0 introduces a new Code directory (or Application_Code, the name is not final yet) that enables you to just deploy the source files of your libraries, and they will get compiled on-the-fly. What you may not know is that you can extend this by creating your own build providers.
    When I first learned about the extensibility of the auto-compilation, I immediately thought about how an Object/Relational  mapping tool could take advantage of it and generate the DAL transparently on-the-fly from the XML mapping file. It would make it marvelously transparent and easy to use, update and manage. An additional bonus is that any change to the xml file would immediately result in Visual Studio Intellisense picking up the change and displaying the new types. Just perfect.
    It seems like I'm not the only one who thought about that: here's an article from Fritz Onion that explains exactly how to do this now, with the public beta of ASP.NET 2.0. Check it out, it works now.
    The possibilities are endless. For example, a business rule engine could use it, or a form generator.
    Play with it, invent great new applications, and if you find anything limiting you in doing so, just tell us about it. Now is the right time.

  • Optimize your images

    It is vitally important that we optimize all the images we ship as resources in the framework: these images will potentially be downloaded several times on each of the pages our users build using the controls that use them.

  • Die, NumLock, Die!

    Why do we still have this stupid NumLock key on modern keyboards? Who still uses it with all of the unlocked keys duplicated about half a centimeter to the left? Hello? Keyboard designers? Please get rid of it now. Everybody hates seeing the cursor go crazy when all they wanted to do was to type a number.
    Now, the people who design keyboards at Microsoft have recently come up with a new way to torture us: the F Lock key. They've decided that we needed new fixed function keys for common tasks such as save or print. This is all very well and I'm sure that having access to these functions with just one keystroke and without having to know complex ctrl key combinations is very useful to disabled persons. But why did they have to put these on our function keys?? Just add new keys, but don't replace useful keys that we're used to. Of course, the new key meanings are on by default and you need to hit F Lock to restore the old F keys. And naturally, every time you reboot, you have to hit it again.
     
    Die, F Lock, die!
     
    Actually, why not make these lock keys real switches if you really want to keep them? After all, they're a matter of personal preference that you just want to set once and forget about. So they could be real switches that you can't accidentally hit. That would be so much better, and it would get rid of the stupid problem that wireless keyboards have which is that they can't display the status of these keys for power consumption reasons.
    Well, in fact, they could also be software settings in the keyboard drivers for all I know.
     
    Finally, what's with the PrtScn key? Whenever I want to do a screen copy, I have to figure out some strange combination of F Lock, Ctrl, Alt and Shift to get the right result. And what does SysRq mean? Does any application still react to ScrLk?
     
    Last minute: To get your F keys back, try this: http://www.mvps.org/jtsang/flock.html

  • The case of the missing data source

    If you've used the beta version of ASP.NET 2.0 a little, the Menu and TreeView controls in particular, you may have noticed that the datasources they consume are different from those that GridView or FormView use. But of course, Menu and TreeView have to use hierarchical data sources, whereas other controls use tabular data sources.
    Tabular data sources that you get out of the box are mainly SqlDataSource and ObjectDataSource. Of course, you can also build your own data source (more on this in later posts). The nice thing is that with ObjectDataSource, you can potentially get data from any data store.
    Now, for hierarchical data sources, you've got XmlDataSource and you've got SiteMapDataSource, and... and that's it. So if you want to populate a Menu or TreeView from a database, you'll pretty much have to do it from code.
    Enter CompositeHierarchicalDataSource... This control I've developed on my free time (which is mainly composed of an aggregation of my serious work's compilation time) composes several tabular data sources into one hierarchical data source using relations.
    Here's a simple page that displays a menu that takes its data from a composition of one ObjectDataSource and two AccessDataSources:

    <%@
    Page Language="C#" debug="true" %>
    <%@
    Register Namespace=MyControls.DataSources.CompositeHierarchicalDataSource TagPrefix=my
    %>
    <!
    DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
    <
    html xmlns="http://www.w3.org/1999/xhtml"
    >

    <
    head id="Head1" runat
    ="server">
       
    <title>CompositeHierarchicalDataSource</title
    >
    </
    head
    >

    <
    body
    >
    <form id="form1" runat
    ="server">
       
    <div
    >
          
    <my:CompositeHierarchicalDataSource runat=server ID=Composite1 RootViewName
    ="Categories:DefaultView">
             
    <DataSources
    >
                
    <asp:ObjectDataSource ID="Categories" Runat="server" TypeName="Categories"
                   
    SelectMethod="GetCategories"
    />
                
    <asp:AccessDataSource ID="SubCategories" Runat="server" DataFile
    ="~/data/things.mdb"
                   
    SelectCommand
    ="SELECT [Id], [CategoryId], [Name] FROM [SubCategories]"/>
                
    <asp:AccessDataSource ID="Things" Runat="server" DataFile
    ="~/data/things.mdb"
                   
    SelectCommand
    ="SELECT [Id], [SubCategoryId], [Name], [Description], [Url] FROM [Things]"/>
             
    </DataSources
    >
             
    <Relations
    >
                
    <my:Relation ParentDataSourceId="Categories" ParentView="DefaultView" ParentColumns
    ="value"
                   
    ChildDataSourceId="SubCategories" ChildView="DefaultView" ChildColumns
    ="CategoryId"/>
                
    <my:Relation ParentDataSourceId="SubCategories" ParentView="DefaultView" ParentColumns
    ="Id"
                   
    ChildDataSourceId="Things" ChildView="DefaultView" ChildColumns
    ="SubCategoryId"/>
             
    </Relations
    >
          
    </my:CompositeHierarchicalDataSource
    >

          
    <asp:Menu Runat=Server ID=myMenu DataSourceID
    =Composite1>
             
    <DataBindings
    >
                
    <asp:MenuItemBinding DataMember="Categories:DefaultView" TextField="text" ValueField="value"
    />
                
    <asp:MenuItemBinding DataMember="SubCategories:DefaultView" TextField="Name" ValueField="Id"
    />
                
    <asp:MenuItemBinding DataMember="Things:DefaultView" TextField="Name" ValueField
    ="Id"
                   
    ToolTipField="Description" NavigateUrlField="Url"
    />
             
    </DataBindings
    >
          
    </asp:Menu
    >
       </div
    >
    </form
    >
    </
    body
    >
    </
    html>
     
    The nice thing is that you can in principle use any tabular data source to build your hierarchical data source. In principle only: this is still a proof of concept and is currently limited to SqlDataSources, ObjectDataSources whose views return DataViews, and datasources whose views implement ITabularDataSourceView. Another problem it currently has is that it loads all of the data at one time. It would be nice to have lazy loading for populate on demand TreeView scenarios.
     
    It's shared source, so you're free to use and modify the code as you wish. Enjoy!
     
    In future posts, I'll explain how it works in details, which should make a nice tutorial on how to develop your own hierarchical data source (hint of other missing data sources: LdapDataSource, FileSystemDataSource).
     
    The GotDotNet CodePlex workspace for this data source can be found here:

  • Number geeks!

    Robin Debreuil has a great post about how the world would be a better place if we had four fingers like the Simpsons (or virtually any cartoon characters). He doesn't say anything about the yellow color or the rubbery hair, but it would sure look cool too.
    His article is amazingly well documented and thought through. You can see that this guy has been thinking about building a new numbering system for years. Very impressive. And very geeky too, in a hilarious kind of way.
    Unfortunately, his proposition for easier arithmetics has even less of a chance to be widely adopted as, say, the US has to adopt the hugely superior metric system or Swatch has to impose its "internet time".
    So it is a total waste of energy, totally useless, impressively time-consuming and funny at the same time.
    And thus highly recommended reading.
     
    A few things worth noting and objections, though:
    - I would actually have loved a numeric system where 4233 sounds like "butthole sniff sniff". How boring would the solar system be if we didn't have Uranus?
    - A complete tutorial with exercises and a diploma at the end would be great (there are exercises at the end of the paper, but that's not enough: I want to learn)
    - As has been noted in the comments, the balanced ternary system is surprisingly good too. Any chance of mixing the two for a balanced ternary bioctal system? And for a better name than that?
    - I'll be saying bioctal too from now on instead of hexadecimal
    - You're completely mad to spend so much time on trying to improve everyone's life whereas you should be working on your SWF/C# project
    - If we forget about one of our fingers, how easier is it to count on them? Anything you can't do with the decimal system?
    - Bioctal sounds like a french anti-acne medication, which is ok as geeks keep their acne quite late.

  • Yield and generics rock!

    public sealed class FilteredEnumerable<T> : IEnumerable<T>, IEnumerable {

      private IEnumerable<T> _enumerable;
      private Predicate<T> _filter;

      public FilteredEnumerable(IEnumerable<T> enumerable, Predicate<T> filter) : base() {
        _enumerable = enumerable;
        _filter = filter;
      }

      IEnumerator<T> IEnumerable<T>.GetEnumerator() {
        foreach (T item in _enumerable) {
          if (_filter == null || _filter(item)) {
            yield return item;
          }
        }
      }

      IEnumerator IEnumerable.GetEnumerator() {
        return (IEnumerator)(((IEnumerable<T>)this).GetEnumerator());
      }
    }

  • The ASP.NET 2.0 page lifecycle in details

    Needless to say, this is a poster you can now find in nearly all offices here in the ASP.NET team at Microsoft. Thanks for the great work, Léo!
    Read it, print it, use it every day!
     
     
    UPDATE: updated the links to the new locations for these resources. The poster would probably need some updating in particular where callbacks are concerned but it's still very useful.

  • What level of control do you need over the rendered HTML?

    I'm answering a post from Dimitri Glazkov here. Dimitri tracked this back to my post about UI reusability. It's probably a good idea to read his post before you go on reading this if you want to understand what this is about.
     
    In an architect's ideal dreamworld, I'd say you're absolutely right, Dimitri. In the real world, though, I'd mitigate this.
    After all, that's what server controls are all about: abstracting the HTML rendering and substituting higher-level abstractions for it. The controls are not ethereal entities, and they need to have some level of control over their rendering to actually work. If you want to have complete control over the rendered HTML, the only thing you can do is output it yourself, and you're back to classic ASP (or PHP). So we should probably be somewhere between complete control and pages made of only server controls.
     
    I'm sure you're aware of this, but I'll say it anyways for your readers and mine who may not be as advanced as you are in ASP.NET.
     
    There are a few things you can do to control the rendering of ASP.NET controls:
    - Use CSS (works with any server-side web technology)
    - Use styles (and in particular their CssClass property to link them to CSS) (v1)
    - Use templates, which give you total control over the HTML that's rendered by some parts of the controls (usually the ones that are the most visual and are not vital for the control to actually work). Templates rule! (v1)
    - Know the control set: there is a fine granularity over the control you can have over the rendering just by choosing the right control. For example, DataGrid, DataList and Repeater are similar list controls that give you more and more control over the final rendering. (v1)
    - Develop your own controls, from scratch or by inheriting from an existing one. This way, you can override part or all of the rendering code. (v1)
    - Use themes and skins to isolate the general presentation of the site. Themes are more or less equivalent to server-side CSS: they act at the same level of abstraction as controls, and enable to set any property (hint: even TEMPLATES) of any control, site-wide or based on a skin ID. Themes are very easy to write as they have the same syntax as a page. (v2)
     
    About adapters, you're right in mentioning that there is a yet unfulfilled potential there. But it may be not in their implementation but in their very use. They may be used for something else than just device adapting. I'll try to blog on that if I have time to experiment with the concept a little more.
     
    Your point about the three roles in the designer is a good one and there may be things more or less along these lines in Orcas. But if you look at it as it is currently, we're already kind of there... You have the visual design view, for designers, you have the HTML view, for what you call the prototype, and you have codebehind for the actual plumbing of the page. Yes, the first two actually act on the same thing, but at a different abstraction level.
    I do not understand your third role, though: why would theme development be the role of an advanced developer? I would have given this role to the graphics designer. Well, at least, the designer can determine the general look of the page and a developer can transform that into a theme.

  • Don't redirect after setting a Session variable (or do it right)

    A problem I see over and over again on the ASP.NET forums is the following:
    In a login page, if the user and password have been validated, the page developer wants to redirect to the default page. To do this, he writes the following code:
    Session["Login"] = true;
    Response.Redirect("~/default.aspx");
    Well, this doesn't work. Can you see why? Yes, it's because of the way Redirect and session variables work.
    When you create a new session (that is, the first time you write to a Session variable), ASP.NET sets a volatile cookie on the client that contains the session token. On all subsequent requests, and as long as the server session and the client cookie have not expired, ASP.NET can look at this cookie and find the right session.
    Now, what Redirect does is to send a special header to the client so that it asks the server for a different page than the one it was waiting for. Server-side, after sending this header, Redirect ends the response. This is a very violent thing to do. Response.End actually stops the execution of the page wherever it is using a ThreadAbortException.
    What happens really here is that the session token gets lost in the battle.
    There are a few things you can do to solve this problem.
    First, in the case of the forms authentication, we already provide a special redirect method: FormsAuthentication.RedirectFromLoginPage. This method is great because, well, it works, and also because it will return the user to the page he was asking for in the first place, and not always default. This means that the user can bookmark protected pages on the site, among other things.
    Another thing you can do is use the overloaded version of Redirect:
    Response.Redirect("~/default.aspx", false);
    This does not abort the thread and thus conserve the session token. Actually, this overload is used internally by RedirectFromLoginPage. As a matter of facts, I would advise to always use this overloaded version over the other just to avoid the nasty effects of the exception. The non-overloaded version is actually here to stay syntactically compatible with classic ASP.
    UPDATE: session loss problems can also result from a misconfigured application pool. For example, if the application pool your site is running is configured as a web farm or a web garden (by setting the maximum number of worker processes to more than one), and if you're not using the session service or SQL sessions, incoming requests will unpredictably go to one of the worker processes, and if it's not the one the session was created on, it's lost.
    The solutions to this problem is either not to use a web garden if you don't need the performance boost, or use one of the out of process session providers.
    Thanks to Frédéric Gareau for pointing that out.
    UPDATE 2: Another thing that can cause similar problems is if your server has a name that contains underscores. Underscores are not allowed in host names by RFC 952 and may interfere with the ability to set cookies and thus to persist sessions.
    UPDATE 3: It appears like some bug fixes to Session have permanently fixed this problem. At least the one caused by the thread aborted redirect. Still, it is good practice to not abort the thread (and thus use the overload with the false parameter).