Why the .NET framework makes for bad web applications

I'm occasionally shocked at some bugs that come up as a result of MS's twisted way of translating any application to Web. .NET makes sense - it really does. It just teaches people to do things *their way* instead of the "Web" way. Take an example of hello world:

If I was making a hello world app in Perl (CGI), I might make 2 files:

form.html

... snip ....
<form action="hello.pl">
<input type="text" name="yourName">
... etc ...

hello.pl

use CGI;
my $q=new CGI;
print $q->header.$q->start_html."Hello ".$q->param('yourName').$q->end_html;

If I gave this to a .NET person to do, they'd do it with one .asp page, with 3 server elements: lblHello, txtName and btnSubmit. The code would be something like:

btnSubmit onClick {
  btnSubmit.visible=false;
  txtName.visible=false;
  lblHello.value="Hello " + txtName.value;
}

There's nothing essentially wrong with this. It would be perfectly correct to do the equivalent using CGI to make one page to handle both scenarios, but some important differences (which the .NET people overlook) include:

  1. In .NET, I'm looking at the widget, rather than the request. Let me elaborate:

    In CGI, I would probably make a hidden variable saying "mode=sayhello" in the form to know I'm after the submit. In .NET I'm relying on the fact that btnSubmit was clicked and it's onClick being called. In the case of a single step (eg form --> final submit) on a given page, this isn't so bad, as we can do something like:

    Page_Load {
      if (Postback) {
        btnSubmit.visible=false;
        txtName.visible=false;
        lblHello.value="Hello " + txtName.value;
      }
    }

    But if it's possible to have more than one way of getting to a postback of the page, things get hairy. And many .NET people don't even think about using a hidden variable. Why? Because...

  2. In .NET the abstraction/translation of the web page to a Window/dialog/etc is complete. Down to the wysiwyg editor which uses absolute positioning with CSS to place elements on the screen (talk about evil, eh? That's called raping CSS ;-)). Now, there's a certain amount of truth in the translation of the webpage to a normal GUI window, and the framework can be used very nicely in the hands of a competant programmer. The problem (this goes back to the Sapir-Whorf programming languages application) is that many times a .NET programmer lacking other background/training in web programming is thinking:

    1. I have 2 widgets on the screen which should be hidden
    2. I want set the visible property of the controls in question to false
    3. btnSubmit.visible=false; txtName.visible=false;

    while a real (no, that's too harsh) classic web programmer is thinking

    1. I have 2 widgets on the screen which should be hidden
    2. I don't want to include the fields in question in the HTML form
    3. btnSubmit.visible=false; txtName.visible=false;

    The difference is subtle, but definately there. I suppose that it pretty much boils down to the fact that the .NET programmer doesn't really think about the HTML aspect of the form. It would never occur to the person to write the 2 page example I did in CGI above, because of another faulty thought process.

    .NET Programmer

    1. I want to use the value from a textbox
    2. lblHello.value="Hello " + txtName.value;

    Web Programmer

    1. I want to use the value from a textbox
    2. I'll need to get the value submitted in the HTTP request
    3. .NET can use a standard HTML form and let me do something like String text=Request.QuesryString("yourName")
    4. But .NET gives me a shortcut of using a "server-side" textbox, which I then need to read a different way (because it screws up the DOM name/id of server-side controls to do its magic)
    5. lblHello.value="Hello " + txtName.value;

    Again, there's nothing intrisicly wrong with thinking the former way, as long as you know it's an environment (.NET) based shortcut of the second. But to a novice .NET programmer, it's all they think of. And once we get to the limitations of the abstraction, it gets stupid.

  3. This really shouldn't be it's own number. It's the same idea as (2) above, with a different spin - and an unacceptable outcome. Let's say I had a checkbox and a text field. I want the textbox to be enable when the checkbox is checked and vice versa. We're not worried about data validation and can assume that at the "normal" form submit (beyond this simple check/text widget), we'll validate data server-side and/or client-side as needed.

    .NET Programmer

    1. I want to change the textbox element based on the checkbox element
    2. To change the textbox element, I want to set it's enabled property
    3. i can get the checkbox status from cbxShowText.value
    4. Furthermore, I can track when the checkbox is changed by using the cbxShowText onClick event handler. (Actually, I think the event is selectedIndexChanged or something like that)
    5. cbxShowText onClick {
        txtName.enabled=cbxShowText.value;
      }

    Whoa! That's not what we expected to see...

    Behind the scenes, MS is taking care of an important set of steps:

    1. Set a javascript handler to set the form to submit when the client side cbxShowText.onClick is triggered
    2. Read the form values from the postback call. Determine which element triggered the postback and hook the onClick event handler

    But it could have been done so much simpler!

    Web Programmer

    1. I want to change the textbox element based on the checkbox element
    2. To change the textbox element, I want to set it's enabled property
    3. i can get the checkbox status from cbxShowText.value
    4. It's a huge waste to send this all to the server, because the server couldn't care less about the state of the box until validation, which is only at the main form submit
    5. I'll write a javascript handler client-side to toggle the disable property of the DOM node of the textbox, which will be called every time the onClick event of the checkbox is triggered. (I won't bother writing the code, because it's irrelevant)

    This is a much more serious problem, since the .NET way is:

    1. Wasting the server's resources
    2. Wasting the client's resources (a full page reload instead of changing the existing page)
    3. Wasting everyone else's resources (if I need to have a full HTTP request/response that wastes bandwidth - especially for a stupid little thing like this inside a massive (50k) form)

    Now the first way wouldn't be so bad if I were doing something more creative with it. Maybe if I had a completely different form to show based on which of a few checkmarks were selected. It's kind of a tough call, because there aren't so many "good" uses. But once it's there, it'll get abused by everyone. The bottom line is that it's the freedom with which .NET makes the 2 hidden steps (e,f) available so easily, that tempts so many programmers to abuse the same wonderful constructs so in such utterly horrible ways.

Anyway, I've rambled enough, and I'm sure I'll get flamed for my efforts anyway, so I'll just quit now...


Valid HTML 4.01!