In many ways, the programming model has gone back to the model that dominated the mid-1970s, when large mainframes served output to terminals connected directly to them. Users would submit jobs to the mainframe and get output to their terminals. So, what's changed here? First, the terminal is a lot fancier-it's a powerful PC running a browser that interprets HTML. The end point to which the browser connects is a Web server (or perhaps a server farm). Finally, the connection protocol used by the client and the server is indirect (and a request can quite literally cross the globe before the user sees a result).
In Web application development, the program's primary job is to receive requests from "out there" and to provide meaningful responses to the requestors. That often means generating complex HTML that renders in a form humans can read on the client's browser. That can be fairly involved, for example, in a modern commercial Web site supporting commerce. Customers will undoubtedly ask about current pricing, request inventory levels, and perhaps even order items or services from the Web site. The process of "generating meaningful HTML for the client" suddenly means doing things such as making database accesses, authenticating the identity of the client, and keeping track of the client's order. Imagine doing all this from scratch!
While frameworks such as classic ASP go a long way toward making Web development more approachable, many features are still left for developers to create on their own (mostly related to the two issues mentioned at the beginning of this section). For example, building a secure but manageable Web site in classic ASP usually meant writing your own security subsystem (or buying one). Managing the state of the UI emitted by your Web site was often a tedious chore as well.