OdeToCode IC Logo

Ultra-Mobile Pricey Computer

Thursday, April 6, 2006 by scott

When news of Project Origami began to spread like avian bird flu, I thought the decision to buy an ultra-mobile PC would be a no-brainer. A small device that can run Word, Outlook, OneNote, and GPS software on a reasonably sized display sounds infinitely useful - all I would need is a fashionable man purse to carry my computer around, right casey?

Now I’ve seen some specs and reviews come on-line.

Dr. Neil is playing with a pre-production UMPC and reports the battery life as ‘just over two hours’. I was hoping for 4.

Meanwhile, the Samsung Q1 is available for preorder in the UK at a price of £800 (almost $1400!). The TabletKiosk eo is also available for pre-order at a price of $900. The troubling fact is $900 only buys 256MB of RAM and a 30GB drive, which is what I expected for $600 entry-level units.

I have not spotted any prices for the unit I’m most interested in, the Asus R2H. The Asus model is rumored to ship with a GPS receiver, fingerprint scanner, and camera. Given the early pricing on other models, I won’t be surprised to see the Asus come in over $1600. At that price point one has to think about the tradeoffs between a UMPC versus a slate or convertible tablet.

Jumping on the first generation UMPCs isn’t the easy decision I first thought. Still, the voice on my shoulder tells me the UMPC could be a lot of fun to develop for…

A Tip for Microsoft Certification Exam Takers

Tuesday, April 4, 2006 by scott

When I took my first certification exam years ago, I spent an inordinate amount of time looking for missing semi-colons, counting parenthesis, and studying variable names. I thought the exam might fool me into picking an answer with a syntax error, and I’d get the question wrong.

After working with the Assessment and Certification Exams team, I wish I knew then what I know now:

There are no trick questions on the Microsoft certification exams.

This is something the cert team wants people to know: if a question is asking about decryption using classes in the .NET framework, the question really is trying to test the candidate’s knowledge of the crypto classes. None of the answers will be wrong because of a missing semicolon. None of the answers will use the class System.Security.Cryptography.MagicDecoderRing, because it doesn’t exist. All the classes are real, there is nothing trying to hide in the code.

This isn’t to say you will never run across a typographical error on an exam. Typos can slip through, unfortunately, but they are rare. When people ask me now if I have any advice, I always say to spend your time finding the answers, instead of spending your time finding the tricks.

Recreational Debugging

Thursday, March 30, 2006 by scott

Eran Sandler runs a great ”Advanced .NET Debugging Blog”. In his recent post “Ambiguous match found in a Web Control - a Possible Bug”, Eran debugs the ASP.NET compiler to find the cause of an error message.

Eran could have fixed the ambiguous match error by changing some code and moving on with life, but it’s hard to pass up a good mystery. It’s fun to figure out why someone else’s code makes our code behave the way it does.

Here is a recent mystery I ran across: why does the following code invoke my workflow’s constructor twice?

WorkflowRuntime runtime = new WorkflowRuntime();
// ...
WorkflowInstance instance;
instance = runtime.CreateWorkflow(
typeof(MyWorkflow));

The obvious first step is to drop a breakpoint in the constructor of MyWorkflow and look at the call stack (Ctrl+Alt+C).

console2.exe!PureCode.MyWorkflow.MyWorkflow() Line 12   
[External Code]    
console2.exe!chapter2_Host.Program.Main() Line 21 + 0x5 bytes

Unfortunately, [External Code] doesn’t tell us anything about where these calls are coming from. This is common when reflection is involved, like when using Activator.CreateInstance.

There are several viable approaches to unravel the mystery, but let’s try the SOS approach. First, we “enable unmanaged code debugging” in the project Debug properties, and then rerun the test harness. When execution stops on the breakpoint in the constructor, switch to the Immediate Window (Ctrl+Alt+I). Now we can load SOS, and look at the call stack with !clrstack.

.load sos
extension C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\sos.dll loaded
!clrstack
PDB symbol for mscorwks.dll not loaded
OS Thread Id: 0x570 (1392)

PureCode.MyWorkflow..ctor()
[GCFrame: 0012ef5c]
[GCFrame: 0012f040]
[HelperMethodFrame_2OBJ: 0012f05c] System.RuntimeTypeHandle.CreateInstance(...)
System.RuntimeType.CreateInstanceSlow(...)
System.RuntimeType.CreateInstanceImpl(...)
System.Activator.CreateInstance(...)
System.Workflow.Runtime.WorkflowDefinitionDispenser.GetRootActivity(...)
System.Workflow.Runtime.WorkflowRuntime.InitializeExecutor(...)
System.Workflow.Runtime.WorkflowRuntime.Load(...)
System.Workflow.Runtime.WorkflowRuntime.GetWorkflowExecutor(...)
System.Workflow.Runtime.WorkflowRuntime.InternalCreateWorkflow(...)
System.Workflow.Runtime.WorkflowRuntime.CreateWorkflow(...)
console2.Program.Main()

The superior stack trace produced by SOS reveals the workflow is instantiated from a method by the name of GetRootActivity. The second time the breakpoints is hit, !clrstack reveals InitializeExecutor as the method calling CreateInstance.

Armed with this bit of knowledge, it’s easy to use Reflector to see what is happening. The very first time the workflow runtime instantiates any given workflow Type, it creates the workflow twice. The runtime passes the first instance through a validation method to ensure the workflow is properly assembled (each activity in a workflow can define custom validations to ensure a proper configuration). The runtime tucks the validated object into a cache, so the runtime will know this workflow Type is “valid” for the duration of the AppDomain. After the first instantiation then, it can skip this validation step. The runtime only creates two instances the first time it sees a given Type.

Another curiosity solved.

Authoring Workflows

Monday, March 27, 2006 by scott

My latest OdeToCode article, Authoring Workflows, looks at how XAML, XOML, partial classes, and compilers all work together in Windows Workflow.

I appreciate any comments, suggestions, and other feedback about the article.

ASP.NET Event Validation and “Invalid Callback Or Postback Argument” : Part II

Wednesday, March 22, 2006 by scott

In the last post we looked at the job event validation performs, and how we can trigger a validation error with some innocent JavaScript. If we receive exceptions because of event validation, we have to disable the feature, or learn how to work with the event validation.

Disable Event Validation

Pros: Easy to do
Cons: Less secure

Bertrand Le Roy wrote a post back in 2004: “Please, please, please, learn about injection attacks!”. Event validation is a feature designed to help prevent injection attacks (of course it can't prevent attacks all by itself).

We can disable event validation for an entire site in the web.config file.

<system.web>
   <
pages enableEventValidation="false"/>
</
system.web>

Alternatively, we can disable validation for a single page.

<%@ Page EnableEventValidation="false" ... %>

Register For Event Validation

Pros: Feel validated
Cons: We need to register all the legal post values before the page is sent to the client - this isn't always possible or practical

When we last left our application, we had a DropDownList with three legal values: “1”, “2”, or “3”. The problem was that client side script was adding a 4th option: “4”. If the user selected the 4th option and posted the form to the server, the server would throw an exception because it didn’t know “4” was a legal value.

The key to passing validation is to let ASP.NET know the value “4” is legal with the RegisterForEventValidation method of the ClientScriptManager class.

RegisterForEventValidation must be called during the rendering phase, so we need to override a Render method. We could start by overriding the Render method of our web form. Plug the following code right below the Page_Load method from the previous post.

protected override void Render(HtmlTextWriter writer)
{
   ClientScript.RegisterForEventValidation(
         _recipeList.UniqueID,
        
"4"
      );

  
base.Render(writer);
}

Remember event validation works by combining the hash of a control’s UniqueID property and a hash of each legal value for that control. The RegisterForEventValidation method accepts both of the calculation inputs as parameters. The method stores the result in a dictionary, and the page adds saves the dictionary as a hidden field on the client.

Adding the RegisterForEventValidation responsibility to the Page class is less than ideal, as the web form suddenly has to know about the DropDownList and its event validation problems. An alternate solution would be to build our own control.

using System;
using System.Web.UI.WebControls;
using System.Web.UI;

namespace OdeToCode.Web.UI.Controls
{
   [
SupportsEventValidation]
  
public class DynamicDropDownList : DropDownList
   {
      
protected override void Render(System.Web.UI.HtmlTextWriter writer)
      {
         Page.ClientScript.RegisterForEventValidation(
              
this.UniqueID,
              
"4"
            );
        
base.Render(writer);
      }
   }
}

A crucial step in the code is to add the SupportsEventValidation attribute to the class. If this attribute is not present, all the RegisterForEventValidation work is in vain. The runtime does not validate events for controls that do not have the SupportsEventValidation attribute present, nor does the runtime does look at the custom attributes of the control’s base class. The table of controls supporting event validation that appeared in the last post was output by a simple program that looped through all the Types in the System.Web assembly looking for the SupportsEventValidationAttribute.

In our example, we knew we only had one additional legal value – the value “4”. We need to call RegisterForEventValidation for every legal value the control might postback. This raises a couple issues because we may not know all of the legal values the control can take. AJAX might populate the control with values from a web service call that is bridged to a third party. Another issue is that the number of legal values might be extremely large.

Unfortunately, ASP.NET doesn’t expose a property to disable event validation for a single control – this would be a nice feature to have. However, if we create a custom control and leave off the SupportsEventValidation attribute, we’ll effectively disable event validation for instances of that class.

ASP.NET Event Validation and “Invalid Callback Or Postback Argument” : Part I

Tuesday, March 21, 2006 by scott

ASP.NET 2.0 added a feature called event validation. Event validation checks the incoming values in a POST to ensure the values are known, good values. If the runtime sees a value it doesn’t know about, it throws an exception.

Invalid postback or callback argument. Event validation is enabled using <pages enableeventvalidation="true" /> in configuration or <%@ page enableeventvalidation="true" %> in a page. For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them. If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation.

The error message is a bit wierd and could use some editing, but if someone is trying to attack the application by spoofing a postback, the event validation exception is a good thing. Event validation can help prevent injection attacks from malicious users who are trying to POST data that doesn’t belong.

If we see this exception during the normal execution of an application, the exception is a bad thing. Let’s look at one scenario where the exception can occur after a legitimate postback, and talk about the implementation of event validation. A future post will discuss possible solutions.

Cause

Imagine we’ve been given the task of writing a web form with a DropDownList, and the DropDownList contains three selections.

<h3>Pick Your Favorite Recipe</h3>
<
asp:DropDownList runat="server" ID="_recipeList">
    <asp:ListItem Value="1">
        Amy's Wasabi Encrusted Tuna
    
</asp:ListItem>
    <asp:ListItem Value="2">
        Big Al's Five Bean Burrito
    
</asp:ListItem>
    <asp:ListItem Value="3">
        Scott's Chocolate Carmel Cheesecake Cookies
    
</asp:ListItem>
</
asp:DropDownList>  

Now, it’s a fairly common scenario for client script to populate the contents of a drop down based upon the value of some other control on the page. For example, a list of states may appear after the user selects a specific country. Let’s simulate that scenario by registering some JavaScript which adds a 4th option to the list.

protected void Page_Load(object sender, EventArgs e)
{
   ClientScript.RegisterStartupScript(
         GetType(),
        
"AddToList",
         script.Replace(
"{_recipeListID}", _recipeList.ClientID),
        
true
      );
}

string script =
  
@"      
     var d = document.getElementById('{_recipeListID}');
     d.options[3] = new Option('George\'s Recipe For Disaster', '4');
   "
;

As long as the user selects recipe 1, 2, or 3, the form will postback without errors. If the user selects option 4, George's Recipe For Disaster, the runtime throws an event validation exception. Disaster indeed!

When ASP.NET rendered the DropDownList it recorded all the possible postback values for the control, It does so by looping through the 3 available ListItems and recording each value. When I say “recorded”, I mean for each item in the list the runtime takes a hash of the control’s UniqueID property, and a hash of the ListItem’s Value property, and XORs the two hash values together. The result of this computation is kept in a list with other allowable hashed values, and the list persists itself as a hidden field in the page.

<input type="hidden"
       name="__EVENTVALIDATION"
       id="__EVENTVALIDATION"
       value="/wEWBQKGg9abDQKd9sHMBgKc9s........"
/>

If the user selects George's Recipe, the browser posts back with a value of “4” for the DropDownList. The runtime will perform the same calculation described earlier: hash(_recipieList.UniqueID XOR hash(“4”)). The runtime will try to find the result of this calculation in the list of allowable values de-serialized from the __EVENTVALIDATION field. The runtime won’t find this value, and will sound the alarm by throwing an exception.

To summarize: the runtime threw an exception because the browser posted a value of “4” for the DropDownList. The runtime thinks the only allowable values are “1”, “2”, and “3”. We added the value “4” as an option using client-side script, so ASP.NET did not know it was legal. ASP.NET calculates the allowable postback values at the last possible moment (inside the Render method of the control).

Just for reference, the following controls support event validation. I’ll provide details on how to know if a control validates events in the next post.

HtmlAnchor HtmlButton HtmlInputButton
HtmlInputCheckBox HtmlInputHidden HtmlInputImage
HtmlInputText HtmlInputPassword HtmlInputRadioButton
HtmlInputReset HtmlInputSubmit HtmlSelect
HtmlTextArea BulletedList Button
Calendar CheckBox Table
ChildTable WizardChildTable DataControlButton
ImageButton DataControlImageButton LinkButton
DataControlLinkButton DataControlPagerLinkButton DataGridLinkButton
DetailsView DropDownList FormView
GridView HiddenField ImageMap
LayoutTable ListBox Menu
PagerTable RadioButton RadioButtonList
TextBox TreeView WizardDefaultInnerTable
CatalogZone ConnectionsZone EditorZone
WebPartZone ZoneButton ZoneLinkButton

Using ASP.NET 2.0 to Streamline Web Application Development

Friday, March 17, 2006 by scott

Microsoft released a curious case study yesterday: “Using ASP.NET 2.0 to Streamline Web Application Development”. (Be aware that if you go to read this document, it is a case study. The document is 100% buzzword complaint and strategically aligned to leverage 80% of your existing infrastructure for a 120% ROI over 2 years).

First, the background section describes the problem Microsoft Human Resource IT was experiencing.

Because of this lack of a standardized architecture and design between applications, HRIT experienced increased costs in application maintenance. For example, HRIT recently spent several thousand dollars over a three-month period to update the privacy statements throughout the HRIT application space. This lack of standardization did not only cost HRIT monetarily, but also in lost productivity.

Reading the problem description you can almost feel the solution jumping out of the page.

The HRIT architecture team determined that it could use the master pages available in ASP.NET 2.0 (described in the "Master Pages" section later in this paper) to create a shell application on which to base all new Web applications in the HRIT application space.

Master pages to the rescue! The description makes the solution sounds as if the master pages are bundled into a Visual Studio Project template. All a developer needs to do is create a new web project with the template, and all the master pages, images, and other common goo appears.

The question is what happens when someone wants to change a master page? A project template is only a starting point and can clone the master page into any number of applications. Since the master pages do not live inside some common area or shared repository, someone needs to apply updated master pages to each application.

Right?

Instead of having to update each individual Web application, HRIT must update only Shell Assemblies to have the legal disclaimer updated on every Web application that is based on Shell Assemblies. The foundation of the shell itself is the master pages available in ASP.NET 2.0.

Here is where the case study lost me. It doesn’t sound as if the solution was a project template as much as a shared class library. I wish the case study went into more detail on how the team built the application, because people are looking for techniques to reuse master pages without resorting to virtual directory tricks. Unfortunately, the study confused and misused a number of technical terms.

My guess is the HRIT solution either uses vdir tricks, or creates an empty master page that is built entirely with code. The code could live in a shared assembly. One of the sticking points with master pages is that the MasterPageFile property of a page requires, well, a file. It would be nice if you could set the master page of a form to a compiled type in a referenced assembly. I can also imagine using the VirtualPathProvider to pull a master page out of a shared assembly's resources, but I'm also pretty sure this would break the designer.