Although I was quite tired from laying tile on Saturday and Sunday, I got up and went to the gym this morning. I swam 1000m – the furthest I have swam in a long, long time.
I am exhausted. What was I thinking when I signed up for a Half Ironman? I’ll be required to swim 1,931 meters for the first leg of my race. July 7, 2012 is not so far away. Only 179 days to go. Ack!
Here it is, the complete list of everything I’ve read in 2011. Meaghan got me a Kindle for our anniversary this year, and just started devouring fiction, a few biographies, and just about anything else that interested me. I don’t think I’ve ever read that much in my life as what I read this past year.
- Watership Down by Richard Adams
- A Dog’s Purpose by W. Bruce Cameron
- Ender’s Game by Orson Scott Card
- Room by Emma Donaghue
- The Ruby Programming Language by David Flanagan and Yukihiro Matsumoto
- Growing Object-Oriented Software, Guided by Tests by Steve Freeman and Nat Pryce
- Making Supper Safe by Ben Hewitt
- The Long Run by Matt Long
- A Game of Thrones: A Song of Ice and Fire Book 1 by George R. R. Martin
- A Clash of Kings: A Song of Ice and Fire Book 2 by George R. R. Martin
- Ghost in the Wires: My Adventures as the World’s Most Wanted Hacker by Kevin Mitnick
- Home from the Vinyl Café by Stuart McLean
- Homeland: The Dark Elf Trilogy, Part 1 by R. A. Salvatore
- Exile: Part 2 by R. A. Salvatore
- We Need to Talk About Kevin by Lionel Shriver
- C# In Depth, 2nd Edition by Jon Skeet
- The Immortal Life of Henrietta Lacks by Rebecca Skloot
- The Help by Kathryn Stockett
I thought it would be cool to make this list, but I really didn’t know it would be that lengthy. I would have never guessed that I had read 18 books in 2011. Bring it on, 2012!
I don’t care if you’re out of color ink. I just want to print a black and white document!

And it’s not even good grammar.
<sigh/>
Between Christmas and New Year’s, I plan to start learning Windows PowerShell. I love my command line, so getting a more powerful command line seems like an ideal thing for me. I usually write little Ruby scripts for the little one-off things that I need to do that a just a little more complicated than a *.bat file. It would be nice to have a native Windows option when it comes to this type of thing. That’s where PowerShell comes in.
Ever run into problems where you really want to see exactly what the user submitted to your web application? I do, especially when I lack a one-to-one relationship between the view and model. This seems like something an action filter should be able to do for me. And as you might have gathered from the title, logging posted form values is something that Rails does out of the box.
There’s a security concern here that we need to concern ourselves with. We’re usually smart enough to encrypt passwords, credit card numbers, and other sensitive information in our databases. And if you’re not encrypting that stuff, you really should be. Like now. We don’t want to introduce a new security hole in our application by logging that information in our database in our logging table. Who cares if your user table is protected if I can just strip the passwords from your log history. This is, obviously, not ideal.
public class LogRequestFormAttribute : ActionFilterAttribute
{
private static readonly string[] defaultProtectedFields = new[] { "CreditCard", "CreditCardNumber", "NewPassword", "NewPasswordConfirmation", "Password", "PasswordConfirmation" };
private static string[] protectedFields;
static LogRequestFormAttribute()
{
Bus.Instance.AddMessageHandlerType(typeof(DebugLogRequestFormMessageObserver));
}
public static IEnumerable<string> ProtectedFormFields
{
get { return protectedFields ?? (protectedFields = ConfigProtectedFormFields.Union(defaultProtectedFields).Distinct().ToArray()); }
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
Bus.Instance.Send(new LogRequestFormMessage(filterContext));
}
private static IEnumerable<string> ConfigProtectedFormFields
{
get
{
string protectedFormFieldsString = ConfigurationManager.AppSettings["ProtectedFormFields"];
if (string.IsNullOrEmpty(protectedFormFieldsString)) return new string[] { };
var protectedFormFields = protectedFormFieldsString
.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries)
.Select(s => s.Trim());
return protectedFormFields;
}
}
}
Right off the bat, I am making sure that form fields called CreditCard, CreditCardNumber, NewPassword, NewPasswordConfirmation, Password, or PasswordConfirmation are listed as protected. Seriously, I don’t care what what your configuration says.
Obviously, this is something Microsoft would never do. Microsoft builds a framework. If you want to use that framework in a hazardous and potential unsecure way, then that’s your problem. Me? I’m not bound by the same constraints.
I do recognize that you may have other values that you want kept out of your logs. Have no fear: it’s easy enough to configure as part of your web.config file.
<add key="ProtectedFormFields" value="CCNumber" />
And with that, we’re now ensuring that anytime a form is posted, any field name CCNumber will be obscured in the message. The trick is in the message. (Don’t worry, it’s not much of a trick.)
public override string ToString()
{
var sb = new StringBuilder();
sb.AppendLine(string.Format("Url: {0}, Controller: {1}, Action: {2}", Url, ControllerName, ActionName));
var keyStrings = new List();
foreach (string key in FormData.AllKeys)
{
var value = GetFormValue(key);
var keyString = string.Format("{0}: {1}", key, value);
keyStrings.Add(keyString);
}
sb.AppendLine(string.Join(", ", keyStrings));
return sb.ToString();
}
internal string GetFormValue(string key)
{
string value;
if (IsProtected(key))
{
var valueLength = (FormData[key] ?? "").Length;
value = new string('*', valueLength);
}
else
{
value = FormData[key] ?? "";
}
return value;
}
What’s Up With The Bus?
The bus is a super simple in-memory message bus infrastructure to send events. It’s part of the Curiosity.Common library. Feel free to check it out!
The DebugLogRequestFormMessageObserver
The debug observer will write to the Visual Studio debug output window. You’ll get something like this.
Url: /home/testform, Controller: home, Action: testform FirstName: Jarrett, LastName: Meyer, Password: **************, PasswordConfirmation: **************, SSN: ***********
Adding Your Own Handler
Want to use log4net? It’s easy enough to add your own message handler.
public class Log4NetLogRequestFormMessageObserver : MessageHandlerBase{ private readonly ILog log = LogManager.GetLogger("form-logger"); public override void Handle(LogRequestFormMessage message) { log.Debug(message); } }
Simple!
Now With More NuGet Awesome
This awesome new feature has been added to Curiosity.Common.Mvc (version 1.8), and is available on NuGet. For more info, check out the wiki page on GitHub.
In every application I’ve every written, I’ve had to deal with state values in some way. At the simplest level, you’ll usually need to know the answer to three questions.
- Is there currently an authenticated user?
- Who is the current user?
- What is the current user allowed to do?
Just about every web application needs to solve these three problems. In fact, this very question was posed by a comment from my previous post. In the commenter’s example, he has a separation of layers that will not allow him to access things like HTTP context or session from his data tier library. (There’s no reference to System.Web from the data tier.)
You know what I’m thinking? This sounds like an interface!
public interface IUserState
{
bool IsAuthenticated { get; }
string UserName { get; }
string[] Roles { get; }
}
This is a bit of a trick in a web environment, because the web is naturally stateless. You can’t use statics the same as you would with a desktop application. You must use a factory, similar to how HttpContext.Current is resolved.
I should point out that the concept of a user state is even lower than your data tier.
public class UserState
{
private static IUserStateFactory factory;
public static IUserState Current
{
get { return factory.UserState; }
}
public static void SetFactory(IUserStateFactory userStateFactory)
{
factory = userStateFactory;
}
}
This part is important: we cannot store the user state instance in a static field. This is one of the biggest sources of problems that I find when working with ASP.NET application. (I’ve seen this all too often in both WebForms and MVC. Remember, the underlying ASP.NET technology is the same.) The static field life cycle is stored within the AppDomain. In an ASP.NET project, this AppDomain is not guaranteed to go to the same user every time. When you have multiple users on a web page. However, we can easily save the factory in a field, since the role of a factory is to create the objects.
Now, we need some implementations that will work with an HTTP session.
public class HttpSessionUserState : IUserState
{
private readonly HttpSessionState session;
public HttpSessionUserState(HttpSessionState session)
{
this.session = session;
}
public bool IsAuthenticated
{
get { return UserName != null; }
}
public string UserName
{
get
{
object userName = session["UserName"];
return (userName != null) ? (string)userName : null;
}
}
public string[] Roles
{
get
{
object roles = session["Roles"];
return (roles != null) ? (string[])roles : new string[] { };
}
}
}
Yes, I prefer to return an empty array of roles, rather than null, in this case. The way .NET deals with nulls is a constant source of frustration, and I hate seeing NullReferenceException’s sprinkled through the error logs.
We also need an implementation of the factory.
public class HttpSessionUserStateFactory : IUserStateFactory
{
public IUserState UserState
{
get
{
var session = HttpContext.Current.Session;
return new HttpSessionUserState(session);
}
}
}
To round out this example we need to register the factory with the static class. This should be done as part of your application startup. In a web app, that means you should put this in your Global.asax file. Create a method like this, and add a call to this method to your Application_Start.
private void RegisterUserStateFactory()
{
var userStateFactory = new HttpSessionUserStateFactory();
UserState.SetFactory(userStateFactory);
}
This is a little lengthy. We’re looking at 5 total classes, but all of the classes are quite small. The first three classes are in a base layer. The specific implementations are in your are part of your startup layer. This works because we are depending on an interface, not a specific implementation. Unit testing is quite easy as well. We can create InMemoryUserState and InMemoryUserStateFactories quite easily, or we can just mock out their implementations.
Back to my previous post
Updating modified entries now needs to look something like this.
private void UpdateModifiedEntries()
{
var modifiedEntries = ChangeTrackerEntries.Where(e => e.State == EntityState.Modified && e.Entity is IAuditable).Select(e => e.Entity);
foreach (var modifiedEntry in modifiedEntries)
{
modifiedEntry.UpdatedAt = DateTime.UtcNow;
modifiedEntry.UpdatedBy = UserState.Current.UserName; // used to be HttpContext.Current.UserName
}
}
Happy to help!
RSS
@jarrettmeyer