What I finally came up with was a simple extension method for the ModelStateDictionary that looks like this:
public static void CleanAllBut(
this ModelStateDictionary modelState,
params string[] includes)
{
modelState
.Where(x => !includes
.Any(i => String.Compare(i, x.Key, true) == 0))
.ToList()
.ForEach(k => modelState.Remove(k));
}
The method removes everything in the model state dictionary that doesn't match one of the "includes" strings. Being a params argument to the method, the call to it becomes very clean and readable (unlike the extension method itself). So I added this call to my controller method:
ModelState.CleanAllBut("username", "password");
While we can use the existing ModelStateDictionary.Remove() method for when we only want to explicitly remove one item, for multi-key removal we could make a similar extension method that takes a list of keys to remove.