In a large saucepan, cook onion in butter over moderately low heat, stirring until it is softened. Stir in the flour and whisk the roux for 3 minutes. Add the milk, whisking until the mixture is thick and smooth. Simmer the sauce for 10 minutes, or until it is thickened to the desired consistency.
In another large saucepan or tall pot, bring water to a boil for asparagus. Once boiling, add asparagus and boil for 8-10 minutes, or until it slightly droops when you lift it out of the water.
Strain the sauce into a bowl, add the gruyére, parmesan, and salt and pepper to taste. Stir the mixture until the cheeses are melted.
Strain the water from the asparagus, transfer to a serving bowl, or plates. Ladle the sauce over asparagus.