May 4th 2009

More thoughts on interviews

My coworkers and I have begun the painful process of hiring again. After conducting too many interviews to count I have a few observations to make.

First and foremost the goal of the interview is to determine if the candidate is a good fit for the position. It’s also important, however, to use the interview to inform the candidate about the company, the position, and the department. There’s little point in finding a great candidate if you haven’t sold the candidate on the position and the team. To do all this consistently with a variety of candidates is difficult and takes practice.

Many interviewers conduct litmus tests more than interviews - they believe there are certain concepts that good developers innately understand. “What is a pointer?”, “How do you model a many-to-many relationship in the database?”, “How do you reverse a singly linked list?”

Skeptics deride these questions as mere trivia. They say that anyone can look algorithms and definitions up in books. The problem with such tests is that they set a bar for “good enough” but provide no way to measure between “good” and “great”. An effective interviewer increases the chances of making good hire by balancing the position requirements against the candidate’s skills, personality, and logistics (salary, title, benefits). Such tests don’t provide enough detail.

Another common problem with interviewing is the basic approach toward the the position. Some want to find candidates who are merely “good enough to be here”. This is a natural by-product of a litmus test interview. Such people honestly believe that interviewing cannot predict with enough accuracy a candidate’s chance of success. They prefer the mantra “Easy to hire, easy to fire”. A similar approach is to compare the candidates against each other and pick the best one. While a candidate may stand out when compared to other candidates, this provides little information about his fit for the position or the team. 

Before every interview I conduct, I review the candidate’s resume in advance. I highlight interview questions that apply to the technologies and experience stated in their resume. I remind myself what my friend told me before my first interview - that the interview process is as much selling the company, position, and team to the candidate as it is about gathering information from the candidate.

Some interviews go well, others do not. Sometimes we just don’t connect very well. Sometimes the problems are more systematic - my questions are too technical and oriented to microsoft technologies than the candidate is comfortable with. It’s important to try and evaluate the efficacy of the interview independently of one’s feelings about the candidate. Day to day most of the candidate’s work will have nothing to do with most of the people he meets during the interview. If we only hired people we related to, we’d never hire across gender or culture lines.

When I changed jobs a while back I lost access to my original list of interview questions. More importantly, I left the interview team that had proved so successful. My former colleagues are far better interviewers than I and I wanted a place to transcribe some of what we developed for future use. The following is what I’ve been able to piece together. In some places I have merely paraphrased their questions poorly. When possible I’ve included their original unblemished questions (with many thanks to Jed and Andrew) and I apologize in advance for the places where I’ve misquoted them.

Phone Screen:

Agenda:

  • Introduction
  • Present interview format
  • Company overview – size, location, culture, business niche
  • Position overview – skills, responsibilities, first project
  • Basic job questions
  • Technical questions (litmus)
  • Round out questions (if the interview looks promising)
  • Next steps
  • Decision timeline
  • Thank you

Questions:

  • Are you familiar with our company?
  • Describe your background and a bit about yourself.
  • Why are you looking for a job?
  • What kind of position are you looking for?
  • How much are you currently making?
  • When can you start?
  • What are the last several books you’ve read?
  • What blogs do you follow?

Technical Questions:

  • What is the difference between a class and an object?
  • What is the difference between a primary key and an index?
  • What is a singleton object? Can you give an example of one in the .net framework?
  • What is a static method? Can you give an example of one in the .net framework?
  • Put the following asp.net control events in order: Page_Load, PreRender, Button_OnClick.

Evaluation:

  • Can you understand this person when they describe their work? What about when they describe technical details?
  • Are the answers to technical questions precise?
  • Does the candidate show an interest in learning and applying new skills?

Computer Algorithms and Concepts Interview:

Questions:

  • What are some common programming patterns? What examples of patterns can you find in existing frameworks - .net, asp.net, jQuery, scriptaculous, Elmah, log4net, linq, etc
  • Pseudo-code the algorithm to reverse a doubly link list.
  • Pseudo-code an implementation for a stack using primitives.
  • Psuedo-code an implementation for removing “z” characters in a C style string.
  • What languages do you enjoy programming in? Why?
  • Imagine an asp.net webform with a single textbox and a single link-button. The user types in a value into the textbox and clicks the link-button.A postback is performed and the page reloads with the textbox already populated. – How does the textbox retain it’s value across the postback? Please be as specific as possible, describing all interactions between systems and communication protocols.
  • Suppose you have two user controls. One containing a databound list and another containing a link button. How would you rebind the list in the first control in the click event of the link button?

Analysis:

  • Can the candidate communicate ideas and concepts well?
  • Do they understand basic patterns and apply them?
  • Do they understand basic algorithms and apply them?
  • Can they site programming principles (SRP, OCP, etc.)?
  • Are they comfortable comparing languages - utility, style, imperative vs. declarative, functional etc.?
  • How did they react when they didn’t know something?
  • How did they work through something they didn’t know?

Manager Interview:

Questions:

tell me about:

  • The best manager (or managerial experience) you had. what did they do well?
  • The worst manager (or experience) you had. what did they do poorly?
  • How you learned a new technology
  • The most difficult challenge you faced (tech or non-tech) and how you overcame it
  • Your proudest moment on the job
  • Working solo / in a small group / in a big group — what do you like about each?
  • Working with teams outside of development (design/qa/etc.)
  • Working with customers
  • Leading on projects/features
  • Working with task/bug tracking systems
  • Aan improvement you would like to have made or did make at your last job
  • Your experience with using/creating standards or best practices

Analysis:

  • How did the candidate work with others? Were those interactions portrayed in a positive light?
  • How driven are they (can they help you make the changes you want to make)?
  • Where they are on the lone wolf scale/mad scientist scale?

 

The goal with the following interview is to evaluate the candidate’s knowledge on a variety of topics. If their resume indicates they have four years of experience programming Asp.net, do they know what you’d expect them to know?

Technical Interview (inital question list from Scott Hanselman here):

Questions:

Web Infrastructure:

  • How many processes can listen on a single TCP/IP port?
  • What is a PostBack?
  • Juxtapose the HTTP verbs GET and POST. What data is contained in each?
  • What kind of data is passed via HTTP Headers?
  • What is HEAD in an html document?
  • Explain how cookies work. Give an example of Cookie abuse.
  • What are the basic html elements that can be placed within the <body> tag?
  • How is a user session maintained by the server?

Basic ASP.Net:

  • When you’re running a component within ASP.NET, what process is it running within on Windows XP? Windows 2000? Windows 2003?
  • What is ViewState? How is it encoded? Is it encrypted? Who uses ViewState?
  • What three Session State providers are available in ASP.NET 1.1? What are the pros and cons of each?
  • What is the difference between a Server Control and a User control? What is a composite control?
  • Put the following events in order for a postback of an aspbutton server control:
    Page_init(), Page_load(), button_onclick()
  • What is the web.config used for?
  • Describe a method to implement paging of a set of records without rerunning the query for each page request. Where can the data be stored?
  • What are the options to handle unhandled exceptions in ASP.Net?
  • What is the difference between ClientId and Id of a web control?
  • What are the difference column types of a datagrid?
  • How do you set the client side onclick event of a control from the code behind?
  • How does a checkboxlist render?
  • How do you dynamically put javascript on a page? Where do you store the javascript in your project?

Advanced ASP.Net:

  • What is the difference between XML Web Services using ASMX and .NET Remoting using SOAP?
  • Are threads reused in ASP.NET between reqeusts? Does every HttpRequest get its own thread? Should you use Thread Local storage with ASP.NET?
  • Is the [ThreadStatic] attribute useful in ASP.NET? Are there side effects? Good or bad?
  • Give an example of how using an HttpHandler could simplify an existing design that serves Check Images from an .aspx page.
  • Describe how a browser-based Form POST becomes a Server-Side event like Button1_OnClick.
  • What kinds of events can an HttpModule subscribe to? What influence can they have on an implementation? What can be done without recompiling the ASP.NET Application?
  • Explain the importance of HttpRequest.ValidateInput()
  • How would one implement ASP.NET HTML output caching, caching outgoing versions of pages generated via all values of q= except where q=5 (as in http://localhost/page.aspx?q=5)?
  • Explain <@OutputCache%> and the usage of VaryByParam, VaryByHeader, VaryByCustom work?
  • Suppose you’re setting javascript functions to control events dynamically. What javascript problems can occur when the page is downloading?
  • What must be true of all objects placed in the session?
  • Suppose you have a datagrid with a template column. The template column contains an asplinkbutton. How can you find a reference to this button in the datagrid’s ItemDataBound Event? Why would the asplinkbutton not be found for a particular row?

Basic OO Developer stuff:

  • Describe what an Interface is and how it’s different from a Class. Contrast the use of an abstract base class against an interface?
  • What is Reflection?
  • What is the difference between a.Equals(b) and a == b? In the context of a comparison, what is object identity versus object equivalence?
  • What is boxing?
  • Explain the differences between public, protected, private and internal (friend in VB)

Basic Windows Stuff:

  • Describe the difference between a Thread and a Process?
  • What is the difference between an EXE and a DLL?
  • What technology enables out-of-proc communication in .NET?

Basic DotNet Stuff:

  • What is strong-typing versus weak-typing? Which is preferred? Why?
  • What is the GAC? What problem does it solve?
  • Conceptually, what is the difference between early-binding and late-binding?
  • How is a strongly-named assembly different from one that isn’t strongly-named?
  • Can DateTimes be null?
  • What are PDBs? Where must they be located for debugging to work?
  • Why is catch(Exception) almost always a bad idea?
  • What is the difference between a Debug and Release build? Is there a significant speed difference? Why or why not?
  • Does JITting occur per-assembly or per-method? How does this affect the working set?
  • Is string a value type or a reference type?
  • Explain the use of virtual, sealed, override, and abstract (C#) or MustOverride, NotInheritable, Overrides, MustInherit (VB.Net)
  • What is the difference between: catch(Exception e){throw e;} and catch(Exception e){throw;}
  • What is the difference between typeof(foo) and myFoo.GetType()?
  • What is a static (Shared in VB) method?
  • What is this (Me in VB)? Can this be used within a static method?
  • What data structures does the .Net framework provide for working with data from a database?
  • What are some options to store database connection settings?

Advanced DotNet Stuff:

  • What is the difference between Finalize() and Dispose()?
  • What is the JIT? What is NGEN? What are limitations and benefits of each?
  • What’s wrong with a line like this? DateTime.Parse(myString);
  • How does the XmlSerializer work?
  • By what mechanism does NUnit know what methods to test?
  • What is remoting? How is it different than DCOM? When is it used?
  • What are the advantages and disadvantages to using the SOAP formatter vs. the binary formatter for serialization? What the advantages and disadvantages to implementing ISerializable for a class?
  • Are collections serializable? Are they threadsafe? Are exceptions serializable?

ASP.NET Ajax:

  • What is Ajax?
  • What is ASP.NET AJAX?
  • What role does the ScriptManager play?
  • Can we use multiple ScriptManager on a page?
  • What is the role of a ScriptManagerProxy?
  • What are the requirements to run ASP.NET AJAX applications on a server?
  • Can I use ASP.NET AJAX with any other technology apart from ASP.NET?
  • How can you cancel an Asynchronous postback?
  • Difference between Server-Side AJAX framework and Client-side AJAX framework?
  • Explain the UpdatePanel?
  • Explain the behavior/extender model. What does it provide over older asp.net javascript implementations.
  • How can you debug ASP.NET AJAX applications?
  • Can we call Server-Side code (C# or VB.NET code) from javascript?
  • Can you nest UpdatePanel within each other?
  • How is the page performance affected by multiple update panels?
  • How can you to add JavaScript to a page when performing an asynchronous postback?
  • Use the ScriptManager class. This class contains several methods like the RegisterStartupScript(), RegisterClientScriptBlock(), RegisterClientScriptInclude(), RegisterArrayDeclaration(),RegisterClientScriptResource(), RegisterExpandoAttribute(), RegisterOnSubmitStatement()
  • Explain differences between the page execution lifecycle of an ASP.NET page and an ASP.NET AJAX page
  • Explain the AJAX Client life-cycle events.
  • Is the ASP.NET AJAX Control Toolkit(AjaxControlToolkit.dll) installed in the Global Assembly Cache?

Database Development (MS SQL oriented):

  • What is a stored procedure? When would you use one?
  • What is a view? When would you use one?
  • What is the difference between a stored procedure and a view?
  • Write a query with a simple join between two tables that have a one to many relationship.
  • What is a temporary table? What are the different types of temporary tables? Why should one try to avoid using them?
  • What is the purpose of the Having clause? What is the purpose of the Group by clause?
  • Suppose you have a large text field in a table with many rows. Give examples of solutions to searching text fields in MS MSQL
  • When do we use the UPDATE_STATISTICS command?
  • Which TCP/IP port does SQL Server run on?
  • Can you tell me the difference between DELETE & TRUNCATE commands?
  • What is the purpose of the transaction log?
  • What is BCP? When do we use it?
  • What is referential integrity? What are the advantages of it?
  • What is database normalization?
  • What are two different kinds of indices in MS SQL?
  • What is the basic functions for master, msdb, tempdb databases?

Analysis:

  • Did the candidate’s knowledge match up to their resume?
  • Did the candidate know the underlying technologies of the frameworks they used? Were they interested in learning?
  • How well did the candidate express themselves? Did they ever say they didn’t know something? Did they try to work through any questions?

No Comments yet »

March 13th 2009

Simple Client-Side Template

I needed an easy way to move a singleton chunk of HTML around the page.  More specifically i needed to insert an event driven piece of HTML into the telerik rad tree view node.  All i needed to do was, 1. create a DIV, the template,  that i could move into other elements. 2. Create one hidden DIV to store the template when it isn’t being shown.  Javascript is pretty slick sometimes, er, atleast it works well for things like managing the DOM!  The few lines of code show the power of this control.

When you want to move the template around you can use the following methods.
Usage

//inserts the template into the content
var contentElement = $get("conatiner1");
contentElement.appendChild(Samples.Template.get_template());

//inserts the template into the hidden storage container.
Samples.Template.storeTemplate();

One of the nice things is that i can attach eventhandlers onto the elements in the template and they remain after moving the template around the DOM. I’ve only tested this in IE6/7 and FF 2/3, but it works great! Here is the asp.net ajax behavior which lets you manage the template through a singleton object.

The Javascript Object

Type.registerNamespace("Samples");

/////////////////////////
//  base class
////////////////////////
Samples.NodeTemplate = function(storageName, templateName) {
    this._storage = null;
    this._storageName = storageName;
    this._templateName = templateName;
};
Samples.NodeTemplate.prototype = {

    onDisabledChanged: function(disabled) { },

    get_template: function() {
        return $get(this._templateName);
    },

    get_storage: function() {
    ///
    /// returns an element where the template is hidden when not inserted into the tree
    ///
        if (!this._storage) {
            this._storage = $get(this._storageName);
        }
        return this._storage;
    },

    get_disabled: function() {
        return this._disabled;
    },
    set_disabled: function(value) {
        if (this._disabled != value) {
            this._disabled = value;
            this.onDisabledChanged(value);
        }
    },

    storeTemplate: function() {
    ///
    /// Finds the template container by id and returns it to the storage area
    ///
        this.get_storage().appendChild(this.get_template());

    }
};
Samples.NodeTemplate.registerClass('Samples.NodeTemplate');

/////////////////////////
//  Singleton Template class
////////////////////////
Samples._Template = function(storageName, templateName) {
    Samples._Template.initializeBase(this, [storageName, templateName]);
};
Samples._Template.prototype = {

    onDisabledChanged: function(disabled) {
        ///
        /// overridable method to handle any changes required on disabled
        ///
        this.get_iconElement().disabled = disabled;
    },

    get_iconElement: function() {
        //would prolly be best to use a helper method since childnodes '
        //differs on a per browser basis, but works for this example
        return this.get_template().childNodes[0];
    }
};
Samples._Template.registerClass('Samples._Template', Samples.NodeTemplate);
//creating instance with a hardcoded id
Samples.Template = new Samples._Template("storage", "template");

Well, this code is setup to work with a pretty specific use case but the base class can be extended into a wide range of neat DOM manipulation tools. This little template is used to choose a type and submit. A simple use case, when you need to turn a region into edit mode you can use this little guy to act as your singleton edit region. Moving it into place whenever you need to, of course you’ll still have to bind data and wire up event handlers, but that’s another blog. The mark-up below shows it can handle asp.net controls, assuming they don’t change over runtime. it’s also important to note that you’ll need to manage the clientstate, if you need to support postbacks anyways.

The HTML

Two things i really like about this code. 1. The power of code is seen in the usage, the behavior is just an overweight static set of helper methods. 2. This feels good to use. Sure, it could be optimized a ton, but i’m not going to for this blog. 3.Javascript singletons are always interesting.


DOWNLOAD THE EXAMPLE CODE HERE

No Comments yet »

February 21st 2009

TinyMCE and .Net integration - validators, gotchas and workarounds

I’ve been working with MoxieCode’s free wywiwyg editor tinyMCE. I made the switch from fckEditor because of tinyMCE’s incredible featureset, small footprint, strong userbase, and high degree of configurability.

For ASP.net developers there is a package that includes controls for integrating tinyMCE as a server control. The server control (Moxiecode.TinyMCE.Web.TextArea) suffers several flaws, specifically:

  • On render the control traverses the page’s entire control hierarchy via the FindAllTinyMCEAreas method. It’s collects all instances on the page so that it can render a single inline script to initialize the page clientside and load all the proper plugins. This traveral of all objects in the Page.Controls object graph can be very costly and the inline javascript  (tinyMCE.init(…)) is rendered before the first instance’s markup.
  • The control does not support encoding on postback - the tinyMCE control supports it client side, but on postback the server control does not decode it.
  • The control does not support asp.net validation.
  • Individual instances are not independently configurable. The initialization script uses the distinct union of all settings applied to all instances.

So I refactored the control to fix these issues.

  • I used the Page.Items dictionary to allow each instance to register itself, avoiding the control tree traveral. 
  • By integrating with the scriptManager’s methods each instance of the tinyMCE control is initialized with specific settings. As with the original control, initial settings are “inherited” from the tinyMCE settings section of the web.config . The “installPath” is always the same across all instances. All other settings are overriden via the Settings collection or as attributes of the control’s markup.
  • The control now supports decoding input that was encoded clientside to work with asp.net request validation. It’s worth noting that if the tinyMCE setting “ask” equals true, then the tinyMCE editor may not be initialized when postback occurs. If the tinyMCE editor is not initialized, the contents of the textArea will not be encoded and on postback a request validation exception could be thrown.
  • The control now supports asp.net validation using custom validators. Before validation occurs, “tinyMCE.triggerSave(); “ needs to be called to force the tinyMCE instances to flush their values to their respective textAreas.  I’ve included custom required and maxLength validators demonstrating this. They are of dubious use, however, since the markup is html encoded it is difficult to check the validitity of a textarea’s length or it’s content.For example, ”<p></p>” is visually equivalent to “” in the browser. As a javascript string ”<p></p>” is considered non-null (length > 0) and it’s encoded text “&lt;p&gt;&lt;p&gt;” is 18 characters long. Though it renders as “” in the browser, the requiredValidator returns true and the maxLength validator will validate against a length of 18 characters.

Check the code out here.

No Comments yet »

January 29th 2009

Some thoughts on jQuery

Like many .net shops, my team has chosen jQuery for its javascript framework. We chose it because most of the team is very new to javascript and jQuery is both accessible and powerful. We’re looking to add client side functionality (mostly UI effects) without concern for cross browser compatibilities.  Modal popups, custom validation, and UI effects are all popular uses of jQuery for us.

Javascript coding is big paradigm shift for Asp.net developers. The standard Asp.net tools (viewstate, update panels, postbacks) complicate even the simplest javascript. Simple operations like:

  • dynamically instantiating javascript objects from the server
  • binding behaviors to controls with runat=”server” (dynamically determined client ids)
  • making asynchronous web service calls
  • reference resource files before they’re needed - e.g. ensure that the $ function is defined before calling $(document).ready(…)

Like other javascript frameworks, jQuery provides some methods for finding and manipulating elements in the DOM. It also provides support for basic ajax calls, array manipulation, and event binding. In essence, it’s 10% helper methods (event binding, collection traversal) and 90% visual effects.

jQuery’s API abstracts away entirely the concept of “execution context“. This concept makes javascript fundamentally different from C# and therefore makes javascript less accessible to C# developers.  Without it, however, jQuery doesn’t provide support for object oriented programming because the developer cannot set the context in which a method will execute. This in turn leads developers to write spaghetti code by binding various DOM events to essentially static functions.

Suppose for example that we have the following requirements:

  1. Show a page with a textbox and a button called “show modal”.
  2. When the button is clicked, show a modal window with an “OK” and a “Cancel” button.
  3. In the modal window, show the content of the textbox.
  4. When the user clicks “Ok” call a web service and pass the value of the textbox.
  5. When the user clicks “Cancel” hide the modal window.

The requirements don’t seem that difficult to implement at first - using the jQuery API we can bind to the click events of the “Show Modal”, “Ok”, and “Cancel” buttons using inline javascript e.g.

$(document).ready(function(){$('OkButton').bind('click',...)}

Note: each function will need to reference at least one DOM element. e.g. the “Ok” button needs to reference the modal window in order to hide it.

What happens, though when our requirements change? For example:

  • The “Show Modal” button is used multiple times on the page.
  • Based on state/permission the “Show Modal” functionality should be disabled.
  • The button controls have “runat=server” on them and therefore have a dynamically determined client id.
  • The page needs to lookup information (possibly via web service) based on the value in the textbox and include that information in the modal window.

As the client side logic becomes more complicated the need to encapsulate the logic into an object(s) grows - a central place for the logic of binding/unbinding events and handling. In javascript methods acquire state through closures - a combination a function a context (state)  - jQuery just isn’t made to do this.

jQuery doesn’t help novice javascript developers learn javascript. It empowers us to create web 2.0 applications with no knowledge beyond web 1.0.

Consider the common pattern event binding pattern in jQuery :

$("a").click(function () {
    alert("Hello World");
});

What happens when the jQuery library hasn’t been downloaded yet? There’s now a race condition between this code being rendered and the jQuery library being referenced.

Here’s another pattern commonly used in jQuery for object initialization:

(function($) { $.plugin = function(data) {... some initialization...})(jQuery);

As soon as the file containing this text is referenced in the page, the plugin is defined and initialized. As a pattern, we’ve now tightly coupled library definition and object instantiation. This works well when initializing singleton objects, but doesn’t work when instantiating multiple objects of the same type, perhaps using the object’s prototype definition.

jQuery’s focus on a static API and lack of support for classes or execution context changes make it somewhat limited for broader application development. The MS Ajax Extensions and prototype frameworks already provide these capabilities. They also provide the backbone for the Ajax Control Toolkit and script.aculo.us respectively. While jQuery is more accessible than these other frameworks, it comes at the cost of learning and leveraging javascript.

1 Comment »

November 3rd 2008

Creating Class Libraries of Asp.Net Web Components

Suppose you have multiple client projects and want to build a reusable framework for them. This framework could include components to build sites (server controls, data control fields, custom datagrid, custom pager etc.). It could also include components such as pages, user controls, and web services.

Scott Gu espouses a strategy for creating user control libraries here, here, and here. The technique involves copying the makrup files from the library “project” to the client “project” using xcopy (robocopy on vista). There are additional articles like this one describing even more ways to achieve partial solutions to this problem.

Depending on your development and deployment needs the solution to this problem will vary. In this article I’ll go through some of the choices available their related trade-offs, give sample applications demonstrating various approaches, and show another method to do this without copying markup files by referencing only the fully compiled library site.

If your library is developed as a web site you can leverage the edit-and-continue feature to create and debug components more quickly. Conversely, since there is no assembly associated with a web site, a web deployment project is needed before components can be referenced in a client application.

Note: In order for components in the app_code directory of the library assembly to be accessible to the client application, library assembly must be referenced by the client application and the setting “Treat As Library Component (remove the App_Code.compiled file)” must be selected in the web deployment project.

By copying the component files to the client application, the library components containing markup are in effect being compiled as part of the client application. This can, however, lead to some issues.

If the web deployment project has “Allow this precompiled site to be updateable” checked, the build will remove the markup from aspx and ascx files and replace them with the text “This is a marker file generated by the precompilation tool, and should not be deleted!”. When the client application builds, Visual Studio tries to build these marker files and  fails on build with an error similar to “The page must have a <%@ webservice class=”MyNamespace.MyClass” … %> directive.”

When copying the markup files directly from the library “project” the files may contain a “codeFile” attribute which will not exist in the client application, causing a compiler warning. Alternatively, when the markup files are copied from the web deployment project’s output, the codeFile attribute has been removed but the compiler will now warn “c:\…\v2.0.50727\Temporary ASP.NET Files\…\App_Web_x4mc84hf.0.cs(134,53): warning CS0108: ‘ASP.library_usercontrols_libraryusercontrol_ascx.Profile’ hides inherited member ‘LibrarySite.Library.UserControls.LibraryUserControl.Profile’. Use the new keyword if hiding was intended.” This is because the web application project already compiled part of the markup into the library assembly, namely the “Profile” and “ApplicationInstance” properties.

To enable web deployment compilation of the client application, the markup files must be copied from the library project (with the codeFile attribute) and not from the web deployment project output, otherwise Aspnet_compile will error.

Another common error is “Compiler Error Message: CS0433: The type ‘ASP.library_usercontrols_libraryusercontrol_ascx’ exists in both ‘c:\…\v2.0.50727\Temporary ASP.NET Files\…\App_Web_empkj51o.dll’ and ‘c:\…\v2.0.50727\Temporary ASP.NET Files\…\assembly\…\LibrarySite.DLL’” This again stems from the re-compilation of library controls in the client application when the client application already references the library assembly. It stems from a situation where the user control/page/webservice has been compiled in the library assembly and is compiled into the client application with the same type name.

A sample of this setup where the library is a web site can be found here (Client application is a vs2k8 web site) and here (Client application is a vs2k8 web application project).

A sample of this setup where the library is a web application project can be found here (Client application is vs2k8 web site) and here (Client application is a vs2k8 web application project).

If you’re using subversion, one final approach to this method involves using svn externs.  An extern link to a child directory of the library is created from a child directory of the client application. When the Client application was compiled, it would also compile these files. Since the client application does not reference the library assembly, there is no type conflict and the controls are only compiled once.

This solution does not work for web services and is quite inflexible.

The basic problem with these approaches is the recompilation of the library controls and the tedious copying of the markup files.

A more flexible approach is to fully compile the library into a single assembly and reference it from the client application as a standard assembly. The problem now is to make the pages, user controls, and web services available to the client application.

In .net 2.0, user controls can be referenced by assembly and namespace in addition to url via the LoadControl method. When referencing precompiled user controls, the key is to reference the compiled markup class, not the codebehind (ASP.library_usercontrols_libraryusercontrol_ascx instead of LibrarySite.Library.UserControls.LibraryUserControl).

To reference pages and web services in the library assembly we need to update our configuration to map requests to these resources to the correct handlers.

In HttpHandlers section of the client application web.config we replace the existing handlers for aspx and asmx as follows:

<remove verb="*" path="*.asmx"/>
<remove verb="*" path="*.aspx"/>

<add verb="*" path="*.aspx" type="LibrarySite.PageHandlerFactory, LibrarySite" validate="true" />
<add verb="*" path="*.asmx" validate="false" type="LibrarySite.AutoDiscoveryWebServiceHandlerFactory, LibrarySite"/>

Now all http requests for .aspx and .asmx files will go through custom IHTTPHandlerFactories to dynamically load pages and web services from the library assembly as necessary. The IHTTPHandlerFactories receives requests and tries to match them to the resource against the full type names in loaded assemblies (e.g. http://localhost/ClientSite/LibrarySite.Library.Pages.LibraryPage.aspx will cause the IHTTPHandlerFactory to load and execute the page LibrarySite.Library.Pages.LibraryPage). If it is unable to find a match, the IHTTPHandlerFactory returns the result of the base (standard) IHTTPHandlerFactory.

The web service implementation for this came from this fantastic posting on codeproject: http://secure.codeproject.com/KB/cpp/WebserviceAndJavaProxy.aspx?display=Print. The author took great care to ensure his solution worked with JSON enabled web services which is very helpful.

In contrast to the web services code, the IHTTPHandlerFactory is much simpler:
Note: the framework caches the mappings between virtualPath and the IHTTPHandler returned so the probe for matching page handlers is only done once per virtualPath.

public override IHttpHandler GetHandler(HttpContext context, string requestType, string virtualPath, string path)
{
 // Try to get the type associated with the request (On a name to type basis)
 Type pageType = this.GetPageServiceType(Path.GetFileNameWithoutExtension(path));
 // if we did not find any send it on to the original ajax script service handler.
 if (pageType == null)
 {
  return base.GetHandler(context, requestType, virtualPath, path);
 }
 else
 {

  return (Page)Activator.CreateInstance(pageType);
 }
}

  /// <summary>
  /// Searches all Services and tries to find a class with the specified name
  /// </summary>
  private Type GetPageServiceType(string pageTypeName)
  {
   // Todo: Caching mechanism for assembly checks
   foreach (Assembly loadedAssembly in AppDomain.CurrentDomain.GetAssemblies())
   {
    Type basePageType = loadedAssembly.GetType(pageTypeName);
    if (basePageType != null)
    {
     var services = from t in loadedAssembly.GetTypes()
           where t.IsSubclassOf(basePageType)
            select t;
     var pageType = services.FirstOrDefault();
     if (pageType != null)
     {
      return pageType;
     }
    }
   }
   return null;
  }

A working sample of all of this is here.

 

 

No Comments yet »

October 20th 2008

Migrating Asp.Net SiteMaps to MS SQL (or fun with MS SQL XML functions)

As part of a larger project, my recent work has involved migrating Asp.Net sitemaps from Xml to MS SQL in order to use a modified version of the SqlSiteMapProvider
Using the xml processing functions new in MS SQL 2005, sitemap files can be imported ease.

A “regular” sitemap file is going to look like this:

<siteMap>
  <siteMapNode title="Home" description="Home" url="~/default.aspx" SomeProperty="someValue">
    <siteMapNode title="Products" description="Our products"
      url="~/Products.aspx"  SomeProperty="someValue"  SomeOtherProperty="someOtherValue">
      <siteMapNode title="Hardware" description="Hardware choices"
        url="~/Hardware.aspx" SomeThirdProperty="someThirdValue"/>
      <siteMapNode title="Software" description="Software choices"
        url="~/Software.aspx" />
    </siteMapNode>
    <siteMapNode title="Services" description="Services we offer"
        url="~/Services.aspx">
        <siteMapNode title="Training" description="Training classes"
          url="~/Training.aspx" />
        <siteMapNode title="Consulting" description="Consulting services"
          url="~/Consulting.aspx" />
        <siteMapNode title="Support" description="Supports plans"
          url="~/Support.aspx" />
    </siteMapNode>
  </siteMapNode>
</siteMap>

using the script here we can populate a table (created with this script).

Note: siteMap nodes can contain custom additional attributes. This script inserts these attributes into the AdditionalProperties column as xml elements:

    <siteMapNode title="Products" description="Our products"
      url="~/Products.aspx"  SomeProperty="someValue"  SomeOtherProperty="someOtherValue">

becomes

<row name="SomeProperty" value="someValue"/>
<row name="SomeOtherProperty" value="someOtherValue"/>

The bulk of the work is down in this query:

select T.c.value('@url', 'nvarchar(255)') as url
, T.c.value('@title', 'nvarchar(255)') as title
, isnull(T.c.value('@description', 'nvarchar(255)'), '') as description
,
	(select U.c.value('local-name(.)', 'varchar(255)') as name , U.c.value('.', 'varchar(255)') as value
	from T.c.nodes('@*[local-name(.) != "url" and local-name(.) != "title" and local-name(.) != "description"]') U(c)
	FOR XML RAW
)
as AdditionalProperties
,T.c.value('../@url', 'nvarchar(255)') as parentUrl
from @xml.nodes('/siteMap//siteMapNode') T(c);

First we parse the xml variable into “rows” using the nodes() function to query to for all the “siteMapNode” elements.
To build the “AdditionalProperties” value for an element node, we do the following:
Parse the element attributes into rows using the XPath query “@*”.
Filter out attribute rows with already defined names (url, title, etc.)
Combine the result set of attributes again into a single entry using the “FOR XML RAW” statement.

Note: this uses the MS SQL functions for untyped XML. If the config has an xmlns attribute, it must be removed before running the script.
To verify the results, run the following query and compare the results to the source config file:

with TMP ([id]
      ,[Title]
      ,[Description]
      ,[Url]
      ,[Roles]
      ,[Parent]
      ,[Sequence]
      ,[AdditionalProperties]
	  ,level)
as (
	SELECT [id]
      ,[Title]
      ,[Description]
      ,[Url]
      ,[Roles]
      ,[Parent]
      ,[Sequence]
      ,[AdditionalProperties]
	  ,0 as level
  FROM [SiteMap] as a
  where parent is null
  union all
	SELECT a.[id]
      ,a.[Title]
      ,a.[Description]
      ,a.[Url]
      ,a.[Roles]
      ,a.[Parent]
      ,a.[Sequence]
      ,a.[AdditionalProperties]
	  ,TMP.level + 1 as level
  FROM [SiteMap] as a
  inner join TMP on a.parent = TMP.id
)
select * from Tmp
order by level, sequence

No Comments yet »

September 22nd 2008

Understanding the Javascript language from a .Net based background

Ever wonder why the Microsoft samples for Ajax always call Function.createDelegate? Why IE6 has such bad memory leak problems? Ever wonder what “this” in javascript refers to?

Javacript is dynamic and interpreted.  Superficially this means that:

  • all objects have a dictionary of properties. One can then modify this dictionary in a very tangible if not intuitive sense by simply setting properties on the object.
    var x = [];
    x.someProperty = 1;
  • the dictionary of properties can be enumerated like a collection
    for (var property in object) {..}
  • arrays are really just objects with properties, the “key” in the dictionary is the array index
    var x = {0:”test”} ;
    is the same as
    x = ["test"];
  • one can use the “eval” statement to translate and execute any string of code
    var p;
    eval(”p=1″);
    will set p equal to one.

There are, however, some more basic questions whose answer is not quite obvious such as:

  • how does one implement inheritance?
  • what does “this” refer to?
  • what is the difference between calling a shared method and an instance method? How does one denote one versus the other?
  • how do I bind an html element’s event to an event handler method on my object?
  • how do I bind an object event to an event handler method on another object?

Most developers assume that Javascript is merely the scripting equivalent of java, but that is not so. To quote Douglas Crockford (JavaScript Architect at Yahoo!):

JavaScript’s C-like syntax, including curly braces and the clunky for statement, makes it appear to be an ordinary procedural language. This is misleading because JavaScript has more in common with functional languages like Lisp or Scheme than with C or Java. It has arrays instead of lists and objects instead of property lists. Functions are first class. It has closures. You get lambdas without having to balance all those parens.

Coming from a .net background, I really don’t remember much about Lisp from college - I remember lists, lots of parentheses, and thinking “It’s all about recursion”. One key feature of Javascript is the closure. To quote wikipedia:

a closure is a function that is evaluated in an environment containing one or more bound variables. When called, the function can access these variables.

A good explanation with examples can be found here. In javascript one can still create object oriented code with private and public methods. It is not, however, intuitive to do so. Opposite from .net, standard class methods are public and accessible as static members. Closures are what gives us state in our methods by binding variables to objects when the method is executed, particularly the “this” object based on context.

In ASP.Net, one adds an event handler like so:
textBox.TextChanged += new EventHandler(SomeObject.TextChangedHandler);

In order for this to work, “SomeObject” must be instantiated and the TextChanged event bound to “SomeObject”. 

Suppose instead that I could create a new method like so:

textBox.TextChanged += new Function(sender,eventArgs=>some other code)

In this case I don’t need to initialize an object or create a static method to handle the TextChanged event. Instead I create an anonymous function and databind the sender and eventArgs parameters to the caller and the caller’s event args.

This is exactly what Javascript has been doing since IE5. The coding emphasis is now on the function to handle the event using databound variables rather than forcing the developer to go through hoops to instantiate objects and wire up methods on those objects. The mechanism that lets you do this is the closure.

Closures lead to certain issues, however, specifically the funarg problem.  Simplify stated a closure may contain a reference to almost any object on the heap. The garbage collector now has to determine if an object is referenced by any closures before destruction. The amount of additional work reqiured for reference counting and object graph traversal is monstrous.

The garbage collection algorithm used by IE6 has been notorious for leaking memory due to poor garbage collection. In November 2007, Microsoft finally recognized the problem and released a partial fix. Microsoft notes here that:

New Web applications live up to higher standards. A page might run for hours without being navigated and retrieve updated information dynamically through Web services. Language features are pushed to the breaking point by combining complex event schemes, object-oriented JScript, and closures to produce entire applications. With these and other changes, certain memory leak patterns are becoming more prominent, especially those previously hidden by navigation.

The good news is that memory leak patterns can be easily spotted if you know what to look for. Most of the troublesome patterns you might face have known workarounds requiring only a small amount of extra work on your behalf. While some pages might still fall prey to small memory leaks, the most noticeable ones can be easily removed….

Closures are a specific form of circular reference that pose the largest pattern to existing Web application architectures. Closures are easy to spot because they rely on a specific language keyword and can be searched for generically

If Javascript is more like scheme or Lisp than Java, then perhaps just learning a new syntax isn’t enough to properly code Javascript. Take a moment and check out Douglas Crockford’s site, particularly his javascript tutorial and javascript history. The more you learn about Javascript, the more you will realize how vastly different it is from any Microsoft technology prior to .net 3.5.  You’ll also get a much better idea how the language constructs of .net 3.5 (lambda expressions, closures, extensions, etc.) are revolutionary in bringing some of the power and flexibility of dynamic languages into static ones without sacrificing compile time type checking and performance.

What is easy and clean in javascript (using the prototype library):

originalList.findAll(function(p) {
  return p.Age > 50;
})

Is now just as easy in .net 3.5:

results = origionaList.Where(p=>p.Age > 50).ToList();

If you’re working on a javascript heavy application, take the time to learn about the language and to lever its inherent features rather than try and bend it to a static language paradigm.

1 Comment »

September 22nd 2008

Testing HTTP Handlers And Modules Without A Web Server

Recently I came across this posting at Cozi Tech Blog:

A Way To Unit Test ASP.NET IHttpHandler Implementations

If you find yourself writing simple HTTP handler code that produces and consumes structured data (for instance, some RESTful application), you may wonder how to test it without fiddling with IIS or configuration files. Here’s a trick to write pure unit tests that verify your IHttpHandler implementation does what you expect. By “pure unit tests”, I mean test code that:

  • works without configuration files (like web.config);
  • needs no servers (like Cassini, IIS, or your own mock HTTP server with full ASP.NET pipeline that you were about to write and debug just before you stumbled upon this article);
  • doesn’t access file system (like ashx files);
  • avoids globals (like HttpContext.Current).
  • At the core of the post is the System.Web.Hosting.SimpleWorkerRequest object in the System.Web.Hosting namespace. It provides an easy way to create http requests and pass them to a handler. The posting gives a nice example and referencing a  custom version of SimpleWorkerRequest on google code.

    The SimpleWorkerRequest implementation referenced has a small bug with querystring values and is limited in scope. Some additional things I wanted to test were HTTP Headers (expiration, mime type, etc.) and file attachments. To test these things, modify WorkerRequestStub to override SendResponseFile, SendKnownResponseHeaders, and SendUnknownResponseHeaders to track and expose the headers and file submissions to the testing container.

    While testing web based UIs is still a difficult and expensive problem there’s no reason testing web services should be.

     

    No Comments yet »

    August 10th 2008

    Properly using the “references” parameter to the MS Ajax $create statement

    Suppose you want to reference a component from another component. The MS Ajax documentation gives the following explanation of the $create function:

    Syntax

    $create(type, properties, events, references, element);

    Arguments

    Parameter Description
    type The type of the component to create.
    properties (Optional) A JSON object that describes the properties and their values.
    events (Optional) A JSON object that describes the events and their handlers.
    references (Optional) A JSON object that describes the properties that are references to other components.
    element (Optional) The DOM element that the component must be attached to.

    The documentation doesn’t provide much information, however, on why you should use the references parameter instead of just using the $find method in the initialize event of your component.

    When the framework renders $create statements through the scriptmanager,  each script descriptor becomes a $create statement in the page source. These statements are executed by the ajax framework when page_load. In order for a component instance to reference another component instance, the object being referenced has to exist already.  If the $create statement for the object being referenced comes after the referencing component’s $create, an error will occur when the $find method is called.

    One way around this is to execute $find every time that the component needs to be referenced. This has performance implications and doesn’t scale well when dealing with collections of components.

    Another way around this is to use the MS Ajax Application_load event using code similar to the following:

    MyNamespace.MyComponent.prototype = {
     initialize: function() {
      MyNamespace.MyComponent.callBaseMethod(this, 'initialize');
    
      this._applicationLoadHandler = Function.createDelegate( this, this.applicationLoad );
      Sys.Application.add_load( this._applicationLoadHandler );
      
     },
    
     applicationLoad: function(sender, e) {
     
      this._componentReference = $find(this._componentReferenceId);
      //Remove the LoadHandler 
      Sys.Application.remove_load( this._applicationLoadHandler );
      this._applicationLoadHandler = null;
     },
     
     set_ComponentReferenceId : function( value ) {
      this._componentReferenceId = value;
     },
      
     get_ComponentReferenceId : function() {
      return this._componentReferenceId;
     }
     // other code
    }

    This approach is explicit and therefore more clear to other developers who might inherit your code. Additionally for collections of components, this method is an excellent option.

    The framework does, however, does provide a way to ensure that when the initialize method is called, the component references have already been set just like other component properties.

    If our custom component inherits from AjaxControlToolkit.ExtenderControlBase, we can add the AjaxControlToolkit.ComponentReference attribute to the property declaration

    <AjaxControlToolkit.RequiredProperty()> _
    <AjaxControlToolkit.ExtenderControlProperty()> _
    <IDReferenceProperty()> _
    <AjaxControlToolkit.ComponentReference()> _
    <AjaxControlToolkit.ClientPropertyName("ComponentReference")> _
    Public Property ComponentReferenceId() As String
     Get
      Return GetPropertyValue(Of String)("ComponentReferenceId", String.Empty)
     End Get
     Set(ByVal value As String)
      SetPropertyValue(Of String)("ComponentReferenceId", value)
     End Set
    End Property
    

    Note: we also need to change the getter/setter methods in the javascript to:

    set_ComponentReference : function( value ) {
      this._componentReference = value;
    },
    get_ComponentReference : function() {
      return this._componentReference;
    }

    Before the initialize method is called the framework will now call set_ComponentReference and pass $find(value from the server side property) as the sole parameter.

    If you’re not extending from AjaxControlToolkit.ExtenderControlBase, you can perform the same operation by using the SetComponent method in the GetScriptDescriptors method:

    Protected Overrides Function GetScriptDescriptors(ByVal targetControl As System.Web.UI.Control) As System.Collections.Generic.IEnumerable(Of System.Web.UI.ScriptDescriptor)
     Dim descriptor As New ScriptBehaviorDescriptor("MyNamespace.MyComponent", targetControl.ClientID)
     descriptor.AddComponentProperty("ComponentReference",Me.ComponentReference)
     ...
     Return New ScriptDescriptor() {descriptor}
    End Sub

    In either event, the net result should be a statment similar to the following generated by the framework in the page source:

    Sys.Application.add_init(function() {
        $create(MyNamespace.MyComponent, {…,”id”:”CustomComponentId”}, null, $find(”RefefencedBehaviorId”), $get(”targetControlId)”));
    });

    No Comments yet »

    August 10th 2008

    Binding MS Ajax Extenders to nested Controls

    The MS Ajax Extender model encourages us to bind html elements to extender properties via clientId. To help make this more declarative, the ajax control toolkit provides property attributes to do this mapping between server side control property and client side javascript accessor methods:

    [IDReferenceProperty(typeof(WebControl))]
    [DefaultValue("")]
    [ExtenderControlProperty]
    [ClientPropertyName("popupElement")]
    [ElementReference]
    [ExtenderControlProperty]

    public string PopupControlID { � }

    In this case, the framework will call a method on the javascript extender called “set_popupElement” and pass it the result of $get(”value from PopupControlId on the server side”).

    This method works well until you want to bind the extender against elements contained in a different naming container. For example, suppose you create a custom extender to populate a popup panel depending on what link a user clicks upon.

    Assume the popup panel control is in fact an asp.net panel. Since panel implements INamingContainer, the custom extender will not locate any elements inside it because the extender’s parent control (the one whose childControls collection it searches) is not the panel itself. Since FindControl() is not recursive, when the extender tries to find the controls inside the panel by Id, it will be unable to locate them.

    One limited workaround is to move the extender inside the asp.net panel. This will work until the extender has to resolve controls both inside and outside the popup panel.

    Another workaround is to set the element ids in the code behind.

    MyExtender.PopupControlId = this.PopupPanel.FindControl(”elementToBindAgainst”);

     this can be quite tedious depending on the number of controls you want to bind against and is less intuitive than the declarative approach.

    Assuming the extender inherits from AjaxControlToolkit.ExtenderControlBase, a more flexible method is to override the ResolveControlProperty method as follows:

     public string SearchContainerPaths { get; set; }
    
      private bool searchControlsInitialized;
      private System.Collections.Generic.List<Control> searchContainers = new System.Collections.Generic.List<Control>();
      protected void ResolveControlProperty(object sender, ResolveControlEventArgs e)
      {
       if (string.IsNullOrEmpty(e.ControlID))
       {
        return;
       }
    
       if (!this.searchControlsInitialized) //check tosee if we've built the "probe" collection of containers to search
       {
        char[] splitChar = new char[] {'.'};
        string[] controlPaths = this.SearchContainerPaths.Split(new char[] {','});
        foreach (string path in controlPaths) {
         string[] subPaths = path.Split(splitChar);
         Control ctl = this.Parent;
         foreach (string controlId in subPaths)
         {
          ctl = ctl.FindControl(controlId);
          if (ctl == null)
          {
           throw new ArgumentException("Cannot find path:" + path);
          }
         }
         this.searchContainers.Add(ctl);
        }
        searchControlsInitialized = true;
       }
       Control tmpCtl = null;
       foreach (Control control in this.searchContainers)
       {
        tmpCtl = control.FindControl(e.ControlID);
        if (tmpCtl != null)
        {
         e.Control = tmpCtl; //the control is found, set it and exit.
         break;
        }
       }
       if (tmpCtl == null) //unable to find control in map paths, throw an exception.
       {
        throw new ArgumentException("Cannot find controlId: " + e.ControlID);
       }
      }

    By setting SearchContainerPaths we can now probe for any controls outside the immediate naming container e.g. SearchContainerPaths=”panel1.panel2,modalPanel” will search the controls collection of panel2 (contained in panel1) and the controls collection of modalPanel.

    This sample gives an example of this using the modalPopupBehavior and a customExtender to bind the popup panel.

     

     

    No Comments yet »

    August 10th 2008

    Perils of Sys.UI.Component and Update Panels

    When writing custom MS Ajax controls, deciding what framework class to inherit from on the client can be tricky. The MS Ajax documentation gives the following explanation of the Sys.UI.Component and it’s associated child classes here:

    Client component object types Summary
    Components
    • Derive from the Component base class.
    • Typically have no UI representation, such as a timer component that raises events at intervals but is not visible on the page.
    • Have no associated DOM elements.
    • Encapsulate client code that is intended to be reusable across applications.
    Behaviors
    • Derive from the Behavior base class, which extends the Component base class.
    • Extend the behavior of DOM elements, such as a watermarking behavior that can be attached to an existing text box.
    • Can create UI elements, although they do not typically modify the basic behavior of the DOM element that they are associated with.
    • If assigned an ID, can be accessed directly from the DOM element through a custom attribute (expando).
    • Do not require an association with another client object, such as a class derived from the Control or Behavior classes.
    • Can reference either a control or a non-control HTML element in their element property.
    Controls
    • Derive from the Control base class, which extends the Component base class.
    • Represent a DOM element as a client object, typically changing the original DOM element’s ordinary behavior to provide new functionality. For example, a menu control might read <li> items from a <ul> element as its source data, but not display a bulleted list.
    • Are accessed from the DOM element directly through the control expando.

    If the difference between Behaviors and Controls isn’t clear to you, you’re not alone. In fact, depending on the version of microsoft documentation, or their horrific msdn documentation, these terms are used almost interchangeably. Generally, behavior, extender, control all refer to the same thing - some custom code written in javascript and instantiated via $create.

    Following the documentation then, if an extender does not have a target control it should inherit from Sys.UI.Component.

    Suppose we have a page that’s using update panels and depending on the user action an extender (inheriting from Sys.UI.Component) is written to the page.

    When a postback occurs the extender will be rendered to the page again. Now there will be a new extender and an existing extender both with the same id. This will cause a javascript error that’s hard to track down, something like “Behavior with Id:? already exists”.

    The original instance of the extender should have been disposed when the update panel framework reloaded the page. Since the extender didn’t have a target element (the core difference between Sys.UI.Component and Sys.UI.Behavior), the framework didn’t know to dispose the extender object when the update panel refreshed its content. 

    To work around this, simply change the extender to inherit from Sys.UI.Behavior and giving it a target element. This will ensure that the object is disposed when the target element is disposed when either the update panel framework destroys the target element or the page is unloaded.

    No Comments yet »

    August 10th 2008

    Converting VB to C# while preserving project references and existing solutions

    We’ve recently begun converting a tremendous amount of code from VB to C#.  Others have much better postings about the pros and cons of chosing VB or C#.  The web is littered with religious rants from haughty C# developers (although they are in the minority of .net developers) about which managed language is better.

    We chose VB originally because it was easier to develop against, it was a language the team was familiar with, and we didn’t have time to ramp both to .net 2.0 and all the quirks of C#. At the time, there were virtually no features of C# that we felt would make our work more efficient.  Over time, however, our team has changed - some of the original developers have moved on and some really smart people with a lot of strong C#/Java experience have joined us. We’ve also had two years to ramp up on .net 2.0 and are now moving on to 3.5 with enthusiasm.  Part of the point in moving to 3.5 is to leverage language features only available in C#.

    The tool we selected for conversion is C-Sharpener for VB.Net because it converts projects in total and does symbol comparison on the output.  Minor quirks of the software include the following:

    1. in VB, int(5) means an array with upper-bound 5, but in C# int(5) means an array with 5 elements and upper-bound 4)
    2. a small issue with complex generics- a dictionary whose value was also a generic does not convert properly
    3. embedded resource references in C# require full names including directory path e.g. to access the embedded resource file name “MyResource.txt” in C#, we would need to call assembly.GetManifestResourceStream( “MyResourceFiles.SomeChildDirectory.MyResource.txt” ) as opposed to the seemingly simpler VB assembly.GetManifestResourceStream( “MyResource.txt” ).
    4. namespace statements are parsed by period. “Namespace A.B.C” becomes
      namespace A
      {
          namespace B
          {
              namespace C
              {

    Once the project is converted, C-Sharpener gives adds the newly created C# project to your solution with the original project name and “_CS” appended to it.

    In order to finish the conversion, we need make changes to unmodified versions solution (.sln file) via text editor.
    note: C-Sharpener will change the solution when it runs to add the new C# project so be sure to revert the solution after the conversion.

    Rather than go through every project’s references and update them to the GUID of the new project we’d like to simply reuse the GUID. This is relatively easy

    1. Open the source VB project’s vbproj file in a text editor and copy the inner text of the ProjectGuid element.
    2. Open the csproj file of the newly created project in a text editor.
    3. update the AssemblyNamespace and RootNamespace elements by removing the extra “_CS”
    4. Update the <ProjectGuid> element - set the inner text of the element to the inner text of the ProjectGuid from the original vb project.
    5. open all solutions containing the original vb project in a text editor.
      your vb project should be referenced in the file like so:Project(”{ProjectTypeGUID}”) = “MyAssembly”, “..\MyAssembly\MyAssembly.vbproj”, “{MyProjectGUID}”
      EndProject
    6. update the path to the newly created cs projectProject(”{ProjectTypeGUID}”) = “MyAssembly”, “..\MyAssemblyInCSharp\MyAssembly.csproj”, “{MyProjectGUID}”
      EndProject

      note: you’ll need to update the path to the csproj and make sure the GUID following it (MyProjectGUID) is the same as the one you pasted from the VB project.

    7. The ProjectTypeGUID indicates to Visual Studio when it tries to compile your solution what kind of project it is - C#, VB, Cobol etc. for example, one of our solutions contains C#, VB, and web deployment projects. It looks like this:Project(”{F184B08F-C81C-45F6-A57F-5ABD9991F28F}”) = “VBProject”, “..\VBProject\VBProject.vbproj”, “{27509F53-2929-459A-8B1E-E03ADA1D8B36}”
      EndProject

      Project(”{2CFEAB61-6A3B-4EB8-B523-560B4BEEF521}”) = “WebDeploymentProject”, “WebDeploymentProject.wdproj”, “{24F3E583-E313-48D6-92ED-A137AC83BBDB}”
      EndProject

      Project(”{F184B08F-C81C-45F6-A57F-5ABD9991F28F}”) = “VBProject2″, “..\VBProject2\VBProject2.vbproj”, “{C73B5D28-96D6-4B29-B90D-E0E3788F0692}”
      EndProject

      Project(”{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}”) = “CSharpProject”, “..\CSharpProject\CSharpProject.csproj”, “{D20CCA67-387E-4B1F-9232-1EEE1359CD9E}”
      EndProject

      note how the second GUID in each project is unique. The first GUID is the one you need to change to tell the solution that the project is no longer a VB project but a C# one instead. For your project, update ProjectTypeGUID to the C# guid - FAE04EC0-301F-11D3-BF4B-00C04F79EFBC.

     

     

    No Comments yet »

    August 10th 2008

    Interface Segregation Principle, Asp.Net, Generics, Interfaces and Covariance, Oh my!

    The interface segregation principle is something most asp.net developers tend to ignore. If I only have one consumer of my business layer (the web/UI layer) why bind against an interface instead of the actual business objects?

    Recently at my job we found ourselves answering that question. We have a single code base and strong continuous integration. Binding to UI interfaces seemed to make things “less agile” :). Now that we’re live, however, things have changed. We’re willing to sacrifice the beautiful patterns we’ve held so dear for the pragmatic concerns of performance and scalability.

    We analyzed our application for problems and began to work around some of our thornier speed issues by writing custom sql that could leverage vendor specific database features and using the caching features of the asp.net framework.

    The problem is that our business entities are too heavy - these custom queries were faster in part because we didn’t need to retrieve all the data necessary to initialize an entity. Additionally, to avoid GC problems, the data we wanted to cache needed to be much “lighter” without references to other objects or data context.

    Our web code was now too rigid. It was binding against strongly typed business objects and needed to bind against interfaces to give us the flexibility and control re-use we needed. We therefore adjusted the necessary Asp.net controls that bound to entities to bind to interfaces instead.

    A problem arose, however, when we went to bind lists. The problem is called covariance and discussed very well here and compared with JAVA here. Basically, to optimize performance, the .net runtime emits code to strongly type collections. This new type has no ties to the interfaces or inheritance hierarchy of the type that it is templating e.g. If A is the base class of B and C, one cannot pass a List<B> to a method expecting a paramter of type List<A>.

    The way around this is actually pretty simple. It’s how most asp.net controls work out of the box. A control’s datasource is simply an object. Only when DataBind() is called is the datasource consumed, and then it’s consumed item by item in the ItemDataBound event where there is no problem casting individual items of a datasource to an interface.

    This paradigm works well. Though we can’t cast strongly typed generic lists based we can cast Foo to IFoo as we consume each item for databinding. The result is a more flexible UI with more code re-use and improved performance.

    No Comments yet »

    August 10th 2008

    Hallmarks of great developers

    At my current employer we’ve spent a long time trying to refine our hiring process. While the process is by no means ideal, after conducting dozens of interviews a few key indictators of great developers have emerged. While not requirements, the developers we’ve hired who are successful and continue to innovate, improvise, and impress all share these qualities.

    1. Reading books.
      This one sounds simple. One applicant I spoke with said “Books make a good reference but I find online resources better for learning and keeping up with technology”. This misses the point entirely. Books are indeed a great reference - they’re more than just a quick answer to a shortlived technical problem. Books help you avoid bothersome technical hurdles in the first place. Jeff Atwood from coding horror expresses this much better here. My team and I spent almost a year working extensively with javascript and the ASP.Net AJAX framework before we ever read a book on the subject. Not suprisingly we learned more from reading the book than we had from all the online references and tutorials. Granted, we were much more receptive to the author’s ideas because we’d already struggled so much with the technology, but reading this book made us better developers by helping us connect existing dots and drawing new pictures.There are numerous excellent books out there about everything that software developers do. From books that expand your horizons, books that help you write better code, books that give you perspective on the bigger picture, books on patterns and practices ,and even fictional books that reinforce what I love about developing software.Many people go out and buy the bible for the next version of some framework or technology. The version they wish they were using, but never end up reading because it doesn’t apply to their work. People who take an interest in doing what they spend 40+ hours a week better are more likely to do a better job for you.
    2. Subscribe to blogs and follow websites
      Blogs keep you abreast of developments in technology. There are really smart people out there with facinating things to say. Following particular blogs shows you have an interest in the world around you and want to see beyond your immediate perspective.Steve Yegge’s blog is brilliant. It’s also opinionated and ignorant of all things microsoft, but he has a lot of really cogent thoughts. Scott Gu’s blog is an invaluable resource to keep up with Microsoft technologies. For year’s Joel Spolsky has provided original thoughts on a wide variety of topics that software developers share in common. I’m glad these guys (and many others) share what they think because there’s a lot to learn from them.
    3. Work to understand the frameworks that they use
      The following are interview questoins I’ve asked:

      • How does the .net xmlSerializer work?
      • How does declarative databinding in the aspx markup work? e.g. <%# DataBinder.Eval(Container.DataItem,”au_id”) %>

      The questions themselves aren’t perfect judges of a developer’s caliber. They do, however, speak to other concerns- Are they using the framework(s) as designed? Is it all voodoo magic or do they know how it works? Before you can understand the limitations of a technology or framework you have to know how it works. Are dynamic languages better or worse than static languages? There are no right answer here, it depends on what you’re trying to do. Neil Ford (from Thoughtworks) said in a talk once that you should generally understand one level deeper than the the code you’re writing. If you’re using asp.net, how does the asp.net framework work? If you’re using a business layer, how does it retrieve and persist data? If you’re writing web pages, how do HTML, HTTP, and web servers work? Technology choices should be based on evidence and fact; learning how things work is a very basic part of that.

    4. Find technology interesting and exciting in its own right
      Most of my time at work is spent with issues that involve code- developing software that is scalable, secure, and efficient while continually work more efficiently. I probably won’t use the next version of Java (I didn’t use the last one much either). I probably won’t make my living coding Ruby on Rails applications. That doesn’t mean that they don’t have interesting innovations, patterns, or paradigms. I love my job, I love doing my job well. Technologies that help me do my job better help make me better and that’s something to be excited about.

    The underlying quality in these traits is passion. People who love developing software, like learning, and want to improve as developers are people that we want to hire.

    No Comments yet »

    May 27th 2008

    Optimize UpdatePanel performance by avoiding unnecessary element disposal

    I fought using update panels for a long time. Every time someone demonstrates the MS AJAX framework they skip the amazing features and go right to update panels. They’d say “Look how easy they are to use!”, “They integrate right into the code you have now.”, and my personal favorite, “This is how you can AJAX enabled your website”. I thought they were a heavy solution filled with problems like smartnav has in asp.net 1.1.
    The MS AJAX framework is much more than just update panels. There’s more to writing AJAX enabled web sites than wrapping your dynamic content inside update panels. However, there’s something I failed to realize- for what they do, update panels are the best tool for the job. If the goal is to asynchronously update content in a page using the same code used to render the content in the first place, updates panels are it. Less obvious features include:

    • Only the data being refreshed is transmitted from the web server
    • UI code uses the same controls to render synchronously or asynchronously
    • The framework manages the loading of additional javascript and css references
    • The framework only renders update panels that have been triggered for refresh
    • There is a simple and effective way to specify which panels get updated on postback
    • Update panels work almost seamlessly with the other parts of the MS AJAX framework - components, controls, and behaviors

    I have now accepted the fact that Microsoft has put more thought, time and money into making update panels better than any homegrown solution.

    In the primer Asp.Net AJAX IN ACTION, the authors take great care to explain precisely how update panels work. They describe how the ajax framework creates and disposes components when an update panel’s contents are updated. For every element in the update panel being disposed, the ajax framework checks to see if there are any controls or behaviors bound to the element that needs to be disposed.

    Note: any components not bound to elements are not disposed when update panels are refreshed. When the page_unload() event calls the dispose method of the components an error may occur because the DOM state has changed and the components don’t reflect it.

    Why bother with object disposal? Why not just replace the innerHTML of the update panel’s div? Julien Lecompte (from Yahoo!) explains a few issues here. Basically, expando attributes on elements cause memory leaks when not disposed properly. Douglas Crockford (also from Yahoo!) describes the basic workaround. Fortunately for us, however, the Microsoft framework does this already in part through the component dispose method.

    When the update panel is about to be loaded, the framework doesn’t know which objects need to be disposed. It has to iterate over all the elements about to be destroyed and check for objects to dispose. The following code is from MicrosoftAjaxWebForms.debug.js (comments in code are mine):

    function Sys$WebForms$PageRequestManager$_updatePanel(updatePanelElement, rendering) {
    	//some code not germane to this post has been omitted here
    	//this is where the existing content is disposed
    	this._destroyTree(updatePanelElement);
    	//and the content is updated
    	updatePanelElement.innerHTML = rendering;
    }
    function Sys$WebForms$PageRequestManager$_destroyTree(element) {
    	if (element.nodeType === 1) {
    		var childNodes = element.childNodes;
    		for (var i = childNodes.length - 1; i >= 0; i--) {
    			var node = childNodes[i];
    			if (node.nodeType === 1) {
    				//if the node has a dispose method, call it
    				if (node.dispose && typeof(node.dispose) === "function") {
    					node.dispose();
    				}
    				//if the node has a sys.ui.control associated with it, call its dispose method
    				else if (node.control && typeof(node.control.dispose) === "function") {
    					node.control.dispose();
    				}
    				//check for sys.ui.behaviors associated with the node and call dispose on each one
    				var behaviors = Sys.UI.Behavior.getBehaviors(node);
    				for (var j = behaviors.length - 1; j >= 0; j--) {
    					behaviors[j].dispose();
    				}
    				//recurse the contents of this node to do it again
    				this._destroyTree(node);
    			}
    		}
    	}
    }

    If you know there are no objects bound to the content of the update panel, Asp.Net AJAX In Action suggests that you can avoid the performance penalty imposed by the framework’s memory leak prevention. They suggest removing the update panel div from the DOM after the asynchronous result is returned and before the framework applies the result to the DOM. We can use the pageLoading event to do this.

    '''
    ''' Exposes methods to increase update panel performance when the panel contains content without sys.ui.controls associated with it
    '''
    '''
    Public NotInheritable Class UpdatePanelRemoveNodeOnPostback         
    
    	'''
    	''' returns string for script to remove the specified control on the client DOM before the page is loaded after an asyncronous postback
    	''' this saves the atlas framework from having to traverse the existing dom elements and remove all behaviors, thereby increasing performance
    	''' NOTE: THIS CAN ONLY BE USED WHEN THE CONTROL HAS NO CLIENT SIDE CONTROLS ASSOCIATED WITH IT, specifically, as is the case with some of our
    	''' gridviews
    	'''
    	'''
    
    	'''
    	'''
    	Public Shared Function CreateScriptToRemoveExistingNodeFromUpdatePanelBeforePageLoad(ByVal control As Control) As String
    		Return String.Format(System.Globalization.CultureInfo.InvariantCulture, Resources.UpdatePanelRemoveNodeOnPageLoading.Script, control.ClientID, control.ClientID, control.ClientID)
    	End Function
    End Class

    The function references a script included as a resource:

    <script type="text/javascript">
    	var pageRequestManager = Sys.WebForms.PageRequestManager.getInstance();
    	pageRequestManager.add_pageLoading(onPageLoading{0});        
    
    	function onPageLoading{1}(sender, e) {
    		var itemToRemove = $('{2}');
    		if (itemToRemove != null) {
    			itemToRemove.remove();
    		}
    	}
    </script>

    One common place I use this is when an update panel contains a gridview. This is an ideal candidate because the amount of html being disposed can be quite large. In the gridview’s container’s preRender event:

    Protected Overrides Sub OnPreRender(ByVal e As System.EventArgs)
    	MyBase.OnPreRender(e)
    	If GridView.Visible Then
    		Dim script As String = UpdatePanelRemoveNodeOnPostback.CreateScriptToRemoveExistingNodeFromUpdatePanelBeforePageLoad(GridView)
    		Me.Page.ClientScript.RegisterStartupScript(Me.GetType, "RemoveGridViewPrePostBackLoad", script)
    	End If
    End Sub

    When the update panel is loaded, the javascript code will fire removing the gridview element from the DOM before the disposal code is fired.

    8 Comments »

    May 27th 2008

    Time based Caching in a Load Balanced ASP.Net Application

    When using the asp.net application cache a common problem occurs when the application scales from a single web server to a web farm. This problem and more are more broadly discussed here.

    One common approach to keep cache items in sync across web servers is use of file dependencies on a central file server. When a depenency file is modified, all web servers in the farm remove the dependent items from their cache.

    This works well until one tries to cache an item for a specified duration without a specific file dependency. Consider a web site that shows “recent blog posts”. The list may be constantly changing and although some latency of the data is allowed(hence the caching), the data must always be consistent no matter which web server serves the response.

    We can use the same file dependency strategy to keep the cache items in sync between web servers. The “trick” is to produce a hash of the data to be cached and include that information when synchronizing the servers.

    If a web server receives a request and does not have the data in its application cache, it must retrieve it.  The server then compares a hash of the data against the contents of a dependency file (unique to that cache item) accessible to all web servers. If the contents of the file are different than the hash generated, the latest results retrieved for the cache item do not match the cache items on other web servers. By replacing the contents of the cache item dependency file with the value of the new hash we can guarantee that the cache items on other web servers will be invalidated and removed.

    A sample project demonstrating this is here.

     

    No Comments yet »

    May 27th 2008

    Class Table Inheritance: An Investigation into SQL Performance

    Class Table Inheritance is a powerful tool when persisting a strong object oriented business model, but what happens when the data size grows? If we know the type of object we’re selecting, the query is straightforward and performs well:

    select
    	 base_class.id
    	,base_class.sub_type
    	,inheriting_class.column1
    ..
    	,inheriting_class.columnn
    from
    	base_class inner join inheriting_class on base_class.id = inheriting_class.base_class_id

    Using multiple tables, requires an inner join to select data and multiple updates to persist it. Outside high volume transaction applications, however, this cost this is negligible.
    The problem begins when we need to select a potentially heterogeneous set of records. The longer the inheritance chain and the larger number of sub-classes the less performant our queries will be.
    Suppose we have a relatively simple object model as follows:

    click the links for scripts to create and populate.

    In order to select a set of records “inheriting” from base_class, the business layer or OR/M will generate a query similar to the following (note I’m not selecting all the records, just a subset akin to the filters one would use in a real application):

    select
    	 base_class.id
    	,A.base_class_id
    	,B.base_class_id
    	,C.base_class_id
    	,case when A.base_class_id is not null then 1 when B.base_class_id is not null then 2 when C.base_class_id is not null then 3 end as clazz_
    from
    	base_class left join inheriting_class_a as A on base_class.id = A.base_class_id
    	left join inheriting_class_b as B on base_class.id = B.base_class_id
    	left join inheriting_class_c as C on base_class.id = C.base_class_id
    where base_class.id % 7 = 1

    On average the query takes 700ms on my machine (dual quad-core x64 xp). If we add in our knowledge of the sub-type into the join, the performance does not improve.

    select
    	 base_class.id
    	,A.base_class_id
    	,B.base_class_id
    	,C.base_class_id
    	,case when A.base_class_id is not null then 1 when B.base_class_id is not null then 2 when C.base_class_id is not null then 3 end as clazz_
    from
    	base_class as base_class left join inheriting_class_a as A on base_class.id = A.base_class_id and base_class.sub_type = 2
    	left join inheriting_class_b as B on base_class.id = B.base_class_id and base_class.sub_type = 0
    	left join inheriting_class_c as C on base_class.id = C.base_class_id and base_class.sub_type = 1
    where base_class.id % 7 = 1

    In fact the query execution plan is still the same despite a unique composite index on id and sub_type. The left joins are simply expensive. We need them to return heterogeneous results but the cost has become prohibitive. The longer the inheritance chain and the larger the number of sub-types, the more drastically the performance will degrade beyond this simple example.
    One workaround is to perform the expensive outer joins on a smaller subset of date. If we execute the same query using a Common Table Expression and filter the rows before doing the outer joins, the cost decreases by 50% to an average of 371ms.

    select
    	 base_class.id
    	,base_class.sub_type
    	,C.base_class_id
    	,B.base_class_id
    	,C.base_class_id
    	,case when A.base_class_id is not null then 1 when B.base_class_id is not null then 2 when C.base_class_id is not null then 3 end as clazz_
    from
    	base_class as base_class left join inheriting_class_a as C on base_class.id = C.base_class_id
    	left join inheriting_class_b as B on base_class.id = B.base_class_id
    	left join inheriting_class_c as C on base_class.id = C.base_class_id
    where base_class.id % 7 = 1

    By comparison, using Single Table inheritance (click links for create and populate scripts), the performace on the following:

    	select id, 1 as clazz_
    	from sub_class_a
    	where id %7 = 1
    union all
    	select id, 2 as clazz_
    	from sub_class_b
    	where id %7 = 1
    union all
    	select id, 3 as clazz_
    	from sub_class_c
    	where id %7 = 1

    is far better than that of the Class Table Inheritance at an average of 140ms. It’s important to note that performance will vary dramatically depending on the size of your data, the “selectiveness” of your where clause and other specifc circumstances.
    From the perspective of query performance, Single Table Inheritance is far more efficient than Class Table Inheritance. Within the context of Class Table Inheritance, what is not so obvious is that the cost of returning heterogenous lists or simply not knowing the sub-type at query time can be quite high. Filtering the records (if possible) before applying the outer joins can drastically improve performance.

    No Comments yet »

    May 27th 2008

    Howto: avoid binding the same eventhandler multiple times to an element event in the MS AJAX framework

    The Microsoft AJAX $addHandler method is a wrapper to the browser specific implementations of the w3c standard e.g. $addHandler(element, eventName, handler).

    Once you’ve bound an event handler to an element, there is no standard way to retrieve the binding information. Javascript frameworks work around this limitation by setting custom properties on the html elements to track handler bindings. As long as handlers are added and removed through the framework things will work as expected with one minor exception. If $addHandler is called twice with the same handler, when the event fires, the handler fires twice.

    The Microsoft AJAX framework doesn’t check whether or not a delegate is already bound before binding it a second time, nor does it provide a means to determine what handlers are already bound. The best way to avoid this condition is by following the MS AJAX pattern for binding behaviors and elements. The pattern dictates that elements are “wrapped” in a one-to-one relationship with controls. When a control is initialized it binds element events to its own internal delegates. When other behaviors need to listen for events, they use the event handling architecture for controls and behaviors by binding against the control, not the element. Mike Ormond’s blog provides a good explanation.

    Occasionally, you have the problem of adding the same handler multiple times. To work around this we need to know a little more about how the Microsoft framework tracks element event bindings.

    When $addHandler is called, Microsoft AJAX adds an expando attribute to the element called “_events”. This is a hash table of the event bindings for the element. Element._events["eventName"] returns an array of delegates bound to the specified element event. The code below simply uses this internal implementation of the MS AJAX framework to avoid duplicate bindings. To use it, simply replace calls to $addHandler and $removeHandler with calls to $addHandlerIfNotDefined and $removeHandlerIfNotDefined.

    $handlerDefined = function(elt, eventName, handler) {
    	// returns true if an eventHandler has been defined for the given element and the given event
    	if ( ( typeof( elt._events ) !== 'object' ) ||
    		 ( elt._events === null ) ) {
    		return false;
    	}
    	var cache = elt._events[eventName];
    	if ( !(cache instanceof Array ) ) {
    		return false;
    	} else {
    		for (var i=0, l = cache.length; i < l; i+=1) {
    				if (cache[i].handler === handler) {
    					return true;
    				}
    		}
    	}
    }    
    
    $addHandlerIfNotDefined = function(elt, eventName, handler) {
    	// ensures the given handler is bound to the given element for the given event
    	if ( !$handlerDefined( elt, eventName, handler ) ) {
    		$addHandler(elt, eventName, handler);
    	}
    }    
    
    $removeHandlerIfNotDefined = function(elt, eventName, handler) {
    	// ensures the given handler is bound to the given element for the given event
    	if ( $handlerDefined( elt, eventName, handler ) ) {
    		$removeHandler(elt, eventName, handler);
    	}
    }

    Note: this solution does not handle new instances of anonymous delegates e.g.
    $addHandlerIfNotDefined(elt, “onclick”, new Function(evt){some code here});
    Since a new anonymous delegate is created each time the handler is added, we would need to compare both the “state” and “code of the delegate for instance equivalence. Determining delegate object equivalence is a difficult thing, the code above compares only delegate instance equivalence.

    No Comments yet »

    April 21st 2008

    Applying for technical jobs? A rough guide

    For the last three years I’ve been involved in our company’s development team hiring process.  We’ve defined it, refined it, reworked it, and reworked it again.  We’ve made mistakes and made great hires.  I thought I’d share a few thoughts on the subject which you may find useful. 

    For every job posting online, we get 100+ applications.  For every diamond in the rough, there are many more applications we wish we didn’t spend time on.  We only want to hire great developers and have a rule: “no false positives”.  Although we may miss a “diamond in the rough” application, we try to make the time we spend hiring as effective as possible.  Usually we “ding” anyone who:

    1. Doesn’t have a cover letter.
    2. Has numerous spelling errors on their resume or cover letter.
    3. Submitted an application that takes us more than 30 seconds to determine what position you’re applying for and where you’re coming from (e.g. current job is “help desk”, but applying for a programmer position; went to school for art history).  For a better explanation check Rand In Repose’s posting.

    So how do you avoid these “dings”?

    1. Have someone proof read your resume
    2. Check out other peoples resumes, e.g.  Resumes That Knock ‘Em Dead and see formats that appear appropriate for the field you work in.
    3. Use a cover letter customized to the position.  Cover Letters That Knock ‘Em Dead has a number of samples to get an idea of the tone and content of what your cover letter should contain.  Make sure to have someone proof read your cover letter before you apply.
    4. Put things on your resume that HR people, recruiters, and automated systems can find.  I don’t mean highlight or boldface all your references to technologies (who started that trend anyways?), use certifications, associations, conferences, and trainings.  HR people aren’t developers.  They don’t know the difference between C# and VB.net or smalltalk and Ruby.  They know keywords they’ve been asked to look for, so make their job easier. By getting certifications, you may not be advancing your education so much as easing the first barrier to entry at any organization - survive the resume screening process.  Certs, conferences, and user groups indicate you’re serious about what you do for a career and advancing yourself professionally. HR people like this.

    You’ve submitted your cover letter and resume, and you get a call back.  The usual process is something like this:

    1. HR person/recruiter calls to qualify the application.  They want to sell you on the job - the company, the job itself, the benefits and also determine if this is a good fit for both parties.  They’ll ask the standard personnel questions and more specific questions they’re told to ask. for example
      1. Why are you looking for a job?
      2. When can you start?
      3. What salary are you looking for?
      4. What kind of job are you looking for?
      5. What are your professional goals? -this one is very important. I can’t tell you how many people have applied for developer positions and told me “I want to get into business analysis/project management/developer management” - the job posting was specifically for a software engineer. Why did you apply?
      6. Suppose you and someone have similar resumes. What makes you different?
      7. What books have you read recently?
      8. What blogs do you subscribe to?

      Be prepared for all of these.  The last three are really where we begin to distinguish ambition/character from professional qualifications. They’re good indicators (like education and certification) about what it is you want to do, how motivated you are, and a rough guide to your technical skills.

    2. The technical phone screen.  This person is usually the hiring manager.  His goal is to further qualify you as a potential hire and to help sell you on the job with more details. Expect more technical questions and questions on your experience with certain technologies. 
    3. In person interview.

    Hopefully you made it through the screening process and are asked for a personal interview.   Get there early - “if you’re on time, you’re late”.  Once there, relax, use the bathroom, and review your information again- who the company is, what they do, the job description, and what information you’ve given them (resume, cover letter, references etc.).

    Steve Yegge has a good description of the general onsite interview process and a whole lot more at “get that job at google.” From his posting:

    Every “experienced” interviewer has a set of pet subjects and possibly specific questions that he or she feels is an accurate gauge of a candidate’s abilities. The question sets for any two interviewers can be widely different and even entirely non-overlapping.

     A classic example found everywhere is: Interviewer A always asks about C++ trivia, filesystems, network protocols and discrete math. Interviewer B always asks about Java trivia, design patterns, unit testing, web frameworks, and software project management. For any given candidate with both A and B on the interview loop, A and B are likely to give very different votes. A and B would probably not even hire each other, given a chance, but they both happened to go through interviewer C, who asked them both about data structures, unix utilities, and processes versus threads, and A and B both happened to squeak by.

     That’s almost always what happens when you get an offer from a tech company. You just happened to squeak by. Because of the inherently flawed nature of the interviewing process, it’s highly likely that someone on the loop will be unimpressed with you, even if you are Alan Turing. Especially if you’re Alan Turing, in fact, since it means you obviously don’t know C++.

     The bottom line is, if you go to an interview at any software company, you should plan for the contingency that you might get genuinely unlucky, and wind up with one or more people from your Interview Anti-Loop on your interview loop. If this happens, you will struggle, then be told that you were not a fit at this time, and then you will feel bad. Just as long as you don’t feel meta-bad, everything is OK. You should feel good that you feel bad after this happens, because hey, it means you’re human.

    It helps to understand the perspective of the employer on the interview process. Joel Spolsky is an excellent resource on hiring developers.  His book entitled “Smart And Gets Things done“ and blog posting The Guerrilla Guide to Interviewing are essential resources for companies trying to find great talent. From his posting:

    You should always try to have at least six people interview each candidate that gets hired, including at least five who would be peers of that candidate (that is, other programmers, not managers). You know the kind of company that just has some salty old manager interview each candidate, and that decision is the only one that matters? These companies don’t have very good people working there. It’s too easy to fake out one interview, especially when a non-programmer interviews a programmer.
     
     If even two of the six interviewers thinks that a person is not worth hiring, don’t hire them. That means you can technically end the “day” of interviews after the first two if the candidate is not going to be hired, which is not a bad idea, but to avoid cruelty you may not want to tell the candidate in advance how many people will be interviewing them. I have heard of companies that allow any interviewer to reject a candidate. This strikes me as a little bit too aggressive; I would probably allow any senior person to reject a candidate but would not reject someone just because one junior person didn’t like them.

    Look for passion. Smart people are passionate about the projects they work on. They get very excited talking about the subject. They talk quickly, and get animated. Being passionately negative can be just as good a sign. “My last boss wanted to do everything on VAX computers because it was all he understood. What a dope!” There are far too many people around that can work on something and not really care one way or the other. It’s hard to get people like this motivated about anything.

    Bad candidates just don’t care and will not get enthusiastic at all during the interview. A really good sign that a candidate is passionate about something is that when they are talking about it, they will forget for a moment that they are in an interview.

    When interviewing we want to give the best impression possible. This is both easier and harder than it may seem.  According to Dave Munger in this post and Malcolm Gladwell in his book Blink(well worth reading), you’ll have about six seconds to make that first impression.  Presenting yourself with confidence and a humble smile will go a very long way to set the right tone for your interview.

    Each individual interview will have several distinct sections.

    1. You’ll meet and shake hands.
      A recruiter once told me that at this moment, I should lean forward a little and stand on my toes.  He said it would make me stand up straighter and more importantly it would make me feel a little silly. This would in turn make me smile and relax. When I relaxed, the interviewer would relax.  After interviewing with 4 companies and 20 different people I will tell you, he was exactly right.  As the interviewer of 50+ people for two different companies, I can tell you the opposite is true- the candidates who don’t present themselves well usually have a harder interview as I try to draw them out.
    2. The interviewer will tell you who they are and what they do. 
    3. They’ll ask you some questions. 
      Be polite, be eager, and be positive during all of this. 
    4. Finally they’ll ask you if you have any questions.
      You should always have questions. Questions show you care about the position. It helps draw the interviewer into the conversation.  It’s also one of the only places during the interview process where you’ll get an idea what the job would actually be like.  Questions like: 

      • Who would I be working with? (Are they of your caliber? Are they as motivated as you are?)
      • What would be the first project/team I’d work on here?
      • What would I need to do to meet or exceed expectations after 6 months? (OK this one is a little cheesy, but sometimes effective)
      • Who would be my manager?
      • What feedback loop do you have for my performance?
      • What is the primary focus of the position (you may get a different answer depending on who you ask) - technical? interfacing with users? project management?

    So you’re interview is done, and you’re on your way out.  Don’t forget to thank everyone you met, including their “staff”.  Take a moment when you finally get out of there and write down some notes of your impressions (you’ll forget things by the time you get home) what people said, the specifics of the actual job, etc. 

    A few final notes:

    • 2 weeks notice to your current employer is standard - if they expect you to leave without notice, it says something about how much they care about people.
    • Always get time to think about the offer- “I have to speak with my family” is a valid answer.  Anyone who goes for the hard sell is sketchy.
    • If things don’t pan out, it’s probably because someone (and it only takes one) thought you weren’t the best fit.  That may be true, it may not, but better no fit than a bad one. 
    • Big companies can afford a longer ramp up time and better training.  Smaller ones are generally looking for you to hit the ground running.  Don’t be upset if someone thought you’d require a little too much training to be useful to them- it’s them, not you :)

    No Comments yet »

    April 21st 2008

    YSlow and ASP.NET - Expires Header - BuildProvider (Part 3 of 3)

    For the last part of our quest to enable caching of static content by separating it out into directories by version, we want to provide an easy and intuitive way for developers to reference static content from the code behind. e.g.

    Dim linkIcon As New System.Web.UI.WebControls.Image
    linkIcon.ImageUrl = StaticContent.Images.rss_gif

    Under the covers StaticContent.Images.rss_gif resolves to a method call -StaticContent.PathBuilder.ConvertImageUrl(”rss.gif”) (the method is covered in part 2).
    To do this we need a buildProvider (Note: this is not supported in Web Application Projects (WAP) see notes at the end).
    The code is mostly written for us on Dave Transom’s excellent post.
    The slightly modified code is here.
    Now that we have a buildProvider we wire it into the build using the web.config:

    <compilation debug="true" strict="true" explicit="true">
    	<buildProviders>
    		<add extension=".hrefs" type="Savo.Framework.Web.StaticContent.BuildProvider"/>
    	</buildProviders>
    </compilation>

    To configure our BuildProvider create a file with the extension “.hrefs” in your App_Code directory, using some variation on the following:

    <?xml version="1.0" encoding="utf-8" ?>
    <settings
    	namespace=""
    	className="StaticContent"
    	minDepth="1"
    	maxDepth="100"
    	lowercaseUrls="true"
    	includeExtension="true"
    	truncatePathToStartingDepth="true"
    	resourceResolutionFormat='StaticContent.PathBuilder.ConvertStaticContentUrl("{0}")'
    	directoryNamesToIgnore="StaticContent">
    	<files include="\.(gif|jpg|png|css)$" exclude="">
    	<folders include="StaticContent" exclude="App_|Bin|\.svn">
    </settings>

    If you’re using a “Web Application Project”, this method won’t work as per this MS post.  My suggestion is to use a pre-build event (although this has a few extra gotchas) or another framework like slink though I haven’t tried either method.

    No Comments yet »

    April 21st 2008

    YSlow and ASP.NET - Expires Header - Expression Builders (Part 2 of 3)

    Continuing our task of caching indefinitely static content by versioning it, we want to build the framework so that instead of code like this:

    <asp:image imageurl="~/images/rose.jpg" runat="server" id="image1">

    we have this:

    <asp:Image id="image1" imageurl="<%$ Image: rose.jpg %>" runat="server"/>

    The key difference is that we can dynamically assign where the image path for rose.jpg resolves in the latter case. Specifically, we can resolve to applicationPath/versionX.X.X/Images/rose.jpg (or whatever url scheme meets your fancy).

    We need two things. First we create an expressionBuilder object and then tie the custom expressionBuilder into the build. I’m using the VS “WebSite” project, but this should work for “Web Application Projects”.

    The following code draws heavily from this post on Dave Reed’s excellent blog infinitiesloop.

    Imports System.CodeDom
    Imports System.Web         
    
    Namespace StaticContent         
    
    	Public NotInheritable Class PathBuilder         
    
    		Private Shared CssPath As String = String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}/StaticContent/{1}/Css/{{0}}", System.Web.HttpContext.Current.Request.ApplicationPath, System.Configuration.ConfigurationManager.AppSettings("versionNumber")))
    		Private Shared ImagePath As String = String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}/StaticContent/{1}/Images/{{0}}", System.Web.HttpContext.Current.Request.ApplicationPath, System.Configuration.ConfigurationManager.AppSettings("versionNumber")))
    		Private Shared JavascriptPath As String = String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}/StaticContent/{1}/Javascripts/{{0}}", System.Web.HttpContext.Current.Request.ApplicationPath, System.Configuration.ConfigurationManager.AppSettings("versionNumber")))         
    
    		Public Shared Function ConvertCssUrl(ByVal path As String) As String
    			Return String.Format(System.Globalization.CultureInfo.InvariantCulture, CssPath, path)
    		End Function         
    
    		Public Shared Function ConvertImageUrl(ByVal path As String) As String
    			Return String.Format(System.Globalization.CultureInfo.InvariantCulture, ImagePath, path)
    		End Function         
    
    		Public Shared Function ConvertJavascriptUrl(ByVal path As String) As String
    			Return String.Format(System.Globalization.CultureInfo.InvariantCulture, JavascriptPath, path)
    		End Function         
    
    		Private Sub New()
    		End Sub         
    
    	End Class         
    
    	MustInherit Class StaticContentExpressionBuilder
    		Inherits Compilation.ExpressionBuilder         
    
    		Protected Shared evaluationExpression As String         
    
    		Protected MustOverride ReadOnly Property StaticContentExpression() As String         
    
    		Public Overrides Function ParseExpression(ByVal expression As String, ByVal propertyType As System.Type, ByVal context As Compilation.ExpressionBuilderContext) As Object
    			Return String.Format(System.Globalization.CultureInfo.InvariantCulture, StaticContentExpression, expression)
    		End Function         
    
    		Public Overloads Overrides Function GetCodeExpression(ByVal entry As System.Web.UI.BoundPropertyEntry, ByVal parsedData As Object, ByVal context As System.Web.Compilation.ExpressionBuilderContext) As System.CodeDom.CodeExpression
    			Return New CodeSnippetExpression(parsedData.ToString())
    		End Function         
    
    	End Class         
    
    	<Compilation.ExpressionPrefix("Js")> _
     Class JavascriptExpressionBuilder
    		Inherits StaticContentExpressionBuilder         
    
    		Protected Overrides ReadOnly Property StaticContentExpression() As String
    			Get
    				Return "StaticContent.PathBuilder.ConvertJavascriptUrl( ""{0}"" )"
    			End Get
    		End Property         
    
    	End Class         
    
    	<Compilation.ExpressionPrefix("Image")> _
    	Class ImageExpressionBuilder
    		Inherits StaticContentExpressionBuilder         
    
    		Protected Overrides ReadOnly Property StaticContentExpression() As String
    			Get
    				Return "StaticContent.PathBuilder.ConvertImageUrl( ""{0}"" )"
    			End Get
    		End Property         
    
    	End Class         
    
    	<Compilation.ExpressionPrefix("Css")> _
    	Class CssExpressionBuilder
    		Inherits StaticContentExpressionBuilder         
    
    		Protected Overrides ReadOnly Property StaticContentExpression() As String
    			Get
    				Return "StaticContent.PathBuilder.ConvertCssUrl( ""{0}"" )"
    			End Get
    		End Property         
    
    	End Class         
    
    End Namespace

    I’ve chosen to implement several types of static content (css, images, and js) but that’s just a matter of convenience. Clearly this could all be done with a single expression. Note the reason I have placed the content type specific methods on PathBuilder is that I need to call these methods in part three (code-behind) where accessing the expressionBuilder assemblies would be pretty awkward.

    To tie our new expression builders into the build we need to add some entries to the web.config.

    <compilation debug="true" strict="true" explicit="true">
    	<expressionBuilders>
    		<add expressionPrefix="Css" type="StaticContent.CssExpressionBuilder"/>
    		<add expressionPrefix="Image" type="StaticContent.ImageExpressionBuilder"/>
    		<add expressionPrefix="Js" type="StaticContent.JavascriptExpressionBuilder"/>
    	</expressionBuilders>
    </compilation>

    That’s it. Now we can do things in our markup like:

    <asp:image imageurl="Image: rose.jpg" runat="server" id="image1">
    <link rel="stylesheet" href="Css: Fonts.css %>" type="text/css" id="FontsCss" runat="server">

    the image “rose.jpg” and css file “Fonts.css” will be rendered to the page as urls:
    “applicationPath/StaticContent/1.0.0/Images/rose.jpg” and “applicationPath/StaticContent/1.0.0/Css/Fonts.css” respectively.

    1 Comment »

    April 20th 2008

    YSlow and ASP.NET - Concatenating and Minifying Css and Js Resources

    In our code we reference several js libraries (prototype, scriptaculous, custom libraries etc.) and we break our css out into several files (layout, fonts, etc.). We encouraged our developers to use whitespace, comments, descriptive names, and separate files to make code as clear as possible. Clear code, however, results in longer download times for web clients.  We wanted to follow the suggestions from the YUI folks to minify and concatenate our resources so that clear code and fast download times could co-exist.

    The answer was our automated build. It would have the job of minifying the js and css. It would concatenate the resources together into two files - one for js and one for css.

    To use concatenated resources in our code while preserving the ability of developers we work, we changed the the markup section of our master slightly to:

    <head runat="server">
    	<!-- css -->
    	<!--	PLEASE NOTE: CSS and JS ARE COMBINED ON AUTOMATED BUILD
    				Please add entries there as necessary!!
    	-->
    	<link rel="stylesheet" href="Css/Fonts.css" type="text/css" id="FontsCss" runat="server">
    	<link rel="stylesheet" href="Css/Structure.css" type="text/css" id="StructureCss" runat="server">
    	<link rel="stylesheet" href="Css/Hyperlinks.css;" type="text/css" id="HyperlinksCss" runat="server">
    	<link rel="stylesheet" href="Css/Menus.css" type="text/css" id="MenusCss" runat="server">
    	<link rel="stylesheet" href="Css/Concatenated.css;" type="text/css" id="ConcatenatedCss" runat="server" visible="false">
    	<!-- javascript -->
    	<ScriptReference:ScriptRef src="Js/prototype.js" runat="server" ID="UiPrototypeJs">
    	<!-- note there are multiple files downloaded after scriptaculous loads, these files should already be included in the concatenated.js if appropriate-->
    	<ScriptReference:ScriptRef src="Js/library/scriptaculous.js" runat="server" ID="ScriptaculousJs">
    	<ScriptReference:ScriptRef src="Js/library/application.js" runat="server" ID="ApplicationJs">
    	<ScriptReference:ScriptRef src="Js/library/Concatenated.js;" runat="server" ID="ConcatenatedScript" Visible="false">
    </head>

    Note: asp.net doesn’t have a server control for script elements, so we roll our own server control:

    Imports System
    Imports System.Web.UI       
    
    	Public Class ScriptRef
    		Inherits WebControls.Literal       
    
    		Private Const _scriptRefMarkup As String = "<script src="" mce_src=""{0}"" type=""text/javascript""></script>"       
    
    		Public Property Src() As String
    			Get
    				Return Me.Text
    			End Get
    			Set(ByVal value As String)
    				If Not value Is Nothing Then
    					Me.Text = String.Format(Globalization.CultureInfo.InvariantCulture, _scriptRefMarkup, value.Replace("~", System.Web.HttpContext.Current.Request.ApplicationPath))
    				End If
    			End Set
    		End Property       
    
    	End Class

    At runtime we can now choose whether to show the css/js files or our concatenated version:

    Protected Overrides Sub OnInit(ByVal e As System.EventArgs)
    	MyBase.OnInit(e)       
    
    	Dim useConcatenatedJsAndCss As Boolean = False
    	If Not String.IsNullOrEmpty(System.Configuration.ConfigurationManager.AppSettings("useConcatenatedJsAndCss")) AndAlso System.Boolean.TryParse(System.Configuration.ConfigurationManager.AppSettings("useConcatenatedJsAndCss"), useConcatenatedJsAndCss) AndAlso useConcatenatedJsAndCss Then
    		If useConcatenatedJsAndCss Then
    			'NOTE: Whatever we set to visible false here has to be added to the
    			'build to be included in the Concatenated css
    			FontsCss.Visible = False
    			StructureCss.Visible = False
    			HyperlinksCss.Visible = False
    			MenuCss.Visible = False       
    
    			PrototypeJs.Visible = False
    			ScriptaculousJs.Visible = False
    			ApplicationJs.Visible = False       
    
    			UiConcatenatedCss.Visible = True
    			UiConcatenatedScript.Visible = True
    		End If
    	End If
    End Sub

    using the config setting “useConcatenatedJsAndCss”

    	<appSettings>
    		<add key="useConcatenatedJsAndCss" value="false"/>
    	</appSettings>

    For minification, we used the YUICompressor. Download it to a place where the build can find it.

    <target name="CleanCss">
    	<foreach item="File" in="${PathToYourWebSiteBuildOutput}/Css" property="filename">
    		<property name="extension" value="${path::get-extension(filename)}">
    		<property name="extension2" value="${string::to-lower(extension)}">
    		<property name="isCss" value="${string::ends-with(extension2, 'css')}">
    		<if test="${isCss}">
    			<exec program="java">
    				<arg value="-jar">
    				<arg value="${YUICompressorPath}">
    				<arg value="-o">
    				<arg value="${filename}.min">
    				<arg value="${filename}">
    				<arg value="--warn">
    				<arg value="--charset">
    				<arg value="Cp1252">
    			</exec>
    			<move file="${filename}.min" tofile="${filename}" overwrite="true">
    		</if>
    	</foreach>
    </target>       
    
    <target name="CleanJs">
    	<foreach item="File" property="filename">
    		<in>
    			<items>
    				<include name="${PathToYourWebSiteBuildOutput}/Javascripts/**/*.js">
    			</items>
    		</in>
    		<do>
    			<property name="extension" value="${path::get-extension(filename)}">
    			<property name="extension2" value="${string::to-lower(extension)}">
    			<property name="isJs" value="${string::ends-with(extension2,'js')}">
    			<if test="${isJs}">
    				<exec program="java">
    					<arg value="-jar">
    					<arg value="${YUICompressorPath}">
    					<arg value="-o">
    					<arg value="${filename}.min">
    					<arg value="${filename}">
    					<arg value="--preserve-semi">
    					<arg value="--charset">
    					<arg value="Cp1252">
    				</exec>
    				<move file="${filename}.min" tofile="${filename}" overwrite="true">
    			</if>
    		</do>
    	</foreach>
    </target>

    Note: when calling jsmin from the commandline we need to specify the character set for the file we’re compressing or use the default format (ANSI).

    For concatenation we can use the build task “concat”. When concatenating files, order is important so we enumerate the files explicitly:

    <target name="CombineCss">
    	<!-- ordering of concat filesets is nondeterministic, so we concat separately -->
    	<concat destfile="${WebSiteStaticContentVersionDirectoryPath}\Css\Concatenated.css" append="false">
    		<fileset>
    			<include name="${WebSiteStaticContentVersionDirectoryPath}/Css/Fonts.css">
    		</fileset>
    	</concat>
    	<concat destfile="${WebSiteStaticContentVersionDirectoryPath}\Css\Concatenated.css" append="true">
    		<fileset>
    			<include name="${WebSiteStaticContentVersionDirectoryPath}/Css/structure.css">
    		</fileset>
    	</concat>
    	<concat destfile="${WebSiteStaticContentVersionDirectoryPath}\Css\Concatenated.css" append="true">
    		<fileset>
    			<include name="${WebSiteStaticContentVersionDirectoryPath}/Css/Hyperlinks.css">
    		</fileset>
    	</concat>
    	<concat destfile="${WebSiteStaticContentVersionDirectoryPath}\Css\Concatenated.css" append="true">
    		<fileset>
    			<include name="${WebSiteStaticContentVersionDirectoryPath}/Css/Menus.css">
    		</fileset>
    	</concat>
    </target>     
    
    <target name="CombineJs">
    	<!-- ordering of concat filesets is nondeterministic, so we concat separately -->
    	<concat destfile="${WebSiteStaticContentVersionDirectoryPath}\Javascripts\library\Concatenated.js" append="true">
    		<fileset>
    			<include name="${WebSiteStaticContentVersionDirectoryPath}/Javascripts/library/prototype.js">
    		</fileset>
    	</concat>
    	<concat destfile="${WebSiteStaticContentVersionDirectoryPath}\Javascripts\library\Concatenated.js" append="true">
    		<fileset>
    			<include name="${WebSiteStaticContentVersionDirectoryPath}/Javascripts/library/scriptaculous.js">
    		</fileset>
    	</concat>
    	<concat destfile="${WebSiteStaticContentVersionDirectoryPath}\Javascripts\library\Concatenated.js" append="true">
    		<fileset>
    			<include name="${WebSiteStaticContentVersionDirectoryPath}/Javascripts/library/crir.js">
    		</fileset>
    	</concat>
    	<concat destfile="${WebSiteStaticContentVersionDirectoryPath}\Javascripts\library\Concatenated.js" append="true">
    		<fileset>
    			<include name="${WebSiteStaticContentVersionDirectoryPath}/Javascripts/library/builder.js">
    		</fileset>
    	</concat>
    	<concat destfile="${WebSiteStaticContentVersionDirectoryPath}\Javascripts\library\Concatenated.js" append="true">
    		<fileset>
    			<include name="${WebSiteStaticContentVersionDirectoryPath}/Javascripts/library/effects.js">
    		</fileset>
    	</concat>
    	<concat destfile="${WebSiteStaticContentVersionDirectoryPath}\Javascripts\library\Concatenated.js" append="true">
    		<fileset>
    			<include name="${WebSiteStaticContentVersionDirectoryPath}/Javascripts/library/dragdrop.js">
    		</fileset>
    	</concat>
    	<concat destfile="${WebSiteStaticContentVersionDirectoryPath}\Javascripts\library\Concatenated.js" append="true">
    		<fileset>
    			<include name="${WebSiteStaticContentVersionDirectoryPath}/Javascripts/library/controls.js">
    		</fileset>
    	</concat>
    	<concat destfile="${WebSiteStaticContentVersionDirectoryPath}\Javascripts\library\Concatenated.js" append="true">
    		<fileset>
    			<include name="${WebSiteStaticContentVersionDirectoryPath}/Javascripts/library/slider.js">
    		</fileset>
    	</concat>
    </target>

    1 Comment »

    April 20th 2008

    YSlow and ASP.NET - Expires Header (Part 1 of 3)

    At our company there’s a focus on getting our asp.net web application to perform in IE6/7 and FF.  Our site uses javascript and css heavily which results in less than optimal performance.  In an effort to improve performance we took proactive steps by:

    • the size of viewstate and http response on all asp.net requests
    • logging the number of queries used on each http request
    • using the excellent tool YSlow to get insight into the actual content rendered

    In future posts I plan to touch upon changes we made in response to these results including minimizing our javascript and css files with YUICompressor and concatenating the results to reduce the number of http requests through our continuous integration process.

    The specific challenge I hope to illustrate concerns the default asp.net http headers for content expiration.  By default, asp.net and IIS serve resources with “Cache-Control: private”.  When you close your browser (or the current tab) the content may be cached (depending on your browser (FF and IE6/7 each handle this differently). When the user returns to your site he will either re-request the file and receive an HTTP 304 (”not modified since”) response or download the entire file again. 

    In the case where your site has lots of images, js, or css files, you can end up issuing a lot of needless http requests for recurring users.  If instead you were able to set the http cache header to something in the far future, then the browser wouldn’t request the file in the first place.  Scott Hanselman has a good discussion of this behavior here.

    In order to cache items at the client you need a way to version them e.g. “~/images/logo.jpg” becomes “v1.0.0/images/logo.jpg”. This way when the resources change they have new paths. These new paths are served up in your markup- the img.src attribute is now different than anything in cache and the browser must therefore request the new version (whose expiration header is also set to a far future date).

    The catch is that while asp.net uses the ResolveUrl method and natively changes “~/images/logo.jpg” to “/myapplication/images/logo.jpg”, there is no such mechanism built into the framework to make it translate “~/images/logo.jpg” to “/myapplication/v1.0.0/images/logo.jpg”.

    This is a fun problem to solve. It has two parts.

    First we must create a framework so that static content can be served easily from the markup by substituting “~/images/logo.jpg” for “<%$ Images: logo.jpg %>”. 

    Part 2 will be addressed using expressionBuilders  

    Secondly we need to create the framework so that in the code behind, we can replace img.url = “~/images/logo.jpg” with img.url = StaticContent.images.logo_jpg.

    Part 3 will be addressed using a build provider.

    Both parts will require changes to our build process not covered here.  The continuous integration process should include in its build archive a directory of the static content named by the version number (e.g. v1.0.0) and updating a application configuration property with the specific version so that the application can reference the static content directory properly. 

    The Continuous Integration changes will not be covered here because they are very specific to one’s own continuous integration process.  We currently use nant with xmlPreprocess to generate our configuration files for each version and environment (prod, dev, qa, etc.), but there are a ton of ways to do this, all outside of asp.net. Using a small ruby script we generate an additional master settings file to incorporate the latest version number in the master configuration.

    No Comments yet »

    April 20th 2008

    What I wish I knew about Service Broker before I started using it

    My current work involves asyncronous communication between multiple servers. Servers in the web farm submit jobs for processing by various backend server farms. Over time our implementation evolved from a simple stored procedure call that polled a table to a much more scalable and fault tolerant MSMQ implementation.

    We moved to MSMQ because polling SQL Server tables leads to locking issues with multiple pollers and larger data sets.  Unfortunately, the move to MSMQ separated messages from data, requiring complicated logic to simulate distrubuted transactions across queues and the database. We moved to SQL Service Broker because it is designed to handle multiple pollers, utilizes t-sql,and calls are made inside the current t-sql transaction.

    Unfortunately the documentation for Service Broker isn’t all that intuitive and the Microsoft tools (Sql Management Studio in particular) don’t really make things easier. Learning about Service Broker takes time and a healthy dose of experimentation.  Our implementation has been live now for several months and is working well.

    Here are a few things we learned along the way:

    • you can see what messages are in a queue by selecting from it - select * from myQueue.
    • the system views sys.service_queues and sys.transmission_queue are your friends. If messages are sent but don’t show up in the queue, check the reason column of the transmission queue.  Most of the time it is because the database master key permissions aren’t set correctly, particularly if the database has been restored. 
    • permissions need to be granted on queues and services to send and receive from them:
      --Grant the user access to the service
      GRANT SEND ON SERVICE::[Your_Service_Name] TO [domain\john.doe] ;
      --Grant the user send rights
      GRANT RECEIVE ON [Your_Queue_Name] TO [domain\john.doe] ;
      --Grant the user receive rights
      GRANT SEND ON [Your_Queue_Name] TO [domain\john.doe] ;
    • when using Activation on queues the procedure actions are included in the current transaction/
    • sending/receiving messages are included in the current transaction.
    • sql management studio does not script broker objects “naturally” - when you script database objects through the UI, service broker objects aren’t included. When you script service broker objects, permissions aren’t included
    • Alter database your_database set new_broker

      will clear all your queues

    • messages in queues are encrypted by default. All messages are hex encoded.
    • if you use a common data store for each endpoint, keep messages as terse as possible. The actual content of the messages is less important than the message itself. If you need additional data, you can retrieve it from the database.

    Service Broker has more features than any standard user is likely to encounter.  Asyncronous symptoms can be complicated; building a secure, scalable, fault tolerant system takes a lot of forethought.  Until Microsoft better integrates its product we have blogs, technical articles, forums, etc. to help augment the existing information. Good luck.

    2 Comments »

    April 20th 2008

    T-SQL Split - An xml based approach

    When we select information from our database we have to be careful to filter only results that the user has access to, e.g. an user has access to user information in a fixed list of departments:

    Select * from Employee where department_id in (1,3,6)

    The problem is comes when we try to parameterize our query because T-SQL requires a parameter for each item in the “IN” clause.  When we use our OR/M (nHibernate) and the setParameterList method, it creates a query like this:

    sp_executeSql(n'Select * from Employee where department_id in (@p0,@p1,@p2)',
    '@p0 int, @p1 int, @p2 int',
    @p0=1,@p1=3,@p2=6);

    This has a few issues:

    1. As the list size increases, query performance degrades due to the number of parameters.
    2. We risk throwing a “Too many parameters were provided in this RPC request. The maximum is 2100″ error depending on the number of items in the list(s) the query uses.
    3. These queries cannot be cached effectively because of the variations in parameters.

    We considered building a list of comma delimited ids, passing that to SQL as an nvarchar parameter, and using a user defined function like this:

    Select * from SomeTable where id in (dbo.fnSplit(@ids))

    After some investigation, however, we found no standard way to implement the fnSplit function. Everybody has their own version optimized for list size, ordering, and format.

    Instead we serialized the list to xml (pretty easy in.net) and deserialized it using:

    CREATE FUNCTION [dbo].[fn_SplitIntsFromXmlNoPrimaryKey](@input varchar(max))
    RETURNS @retArray TABLE (id int)
    AS
    BEGIN
    	DECLARE @xml xml
    	SET @xml = @input
    	insert into @retArray
    	SELECT   T.id.value('.', 'int') AS id
    	FROM @xml.nodes('/ArrayOfInt/int') T(id)
    	RETURN
    END
    select * from [dbo].[fn_SplitIntsFromXmlNoPrimaryKey] (
    '
      33
      72
      74
      76
      78
      80
    80
     ')

    For larger numbers of ids, performance degraded due to the table scan:
    fnSplitWithNoPrimaryKey
    So we optimized the function by introducing a primary key on the ints:

    CREATE FUNCTION [dbo].[fn_SplitIntsFromXml](@input varchar(max))
    RETURNS @retArray TABLE (id int Primary Key)
    AS
    BEGIN
    	DECLARE @xml xml
    	SET @xml = @input
    	insert into @retArray
    	SELECT   T.id.value('.', 'int') AS id
    	FROM @xml.nodes('/ArrayOfInt/int') T(id)
    	RETURN
    END
    select * from [dbo].[fn_SplitIntsFromXml] (
    '
      33
      72
      74
      76
      78
      80
     ')

    fnSplitWithPrimaryKey
    For several thousand ids, the performance difference was quite dramatic at 1 second versus 13 seconds. Although our testing was light it was conclusive- a primary key allows SQL to avoid using a heap for storing/searching the table valued function result and this is much faster. Since we’re using a single parameter per IN clause, we are no longer limited by the RPC parameter limit, the query plan can be cached, and performance is within limits.
    Happy coding.

    No Comments yet »

    Next »