Sep 3 2011

Data Access in Fail Tracker–Row-Level Security with LINQ to NHibernate

Category: Fail Tracker | NHibernateMatt @ 03:17

This is the third and probably final post about how data access is performed in Fail Tracker.  I’ve previously shown you the basics of how its repository-pattern based approach and how a shared base SpecsFor test fixture is leveraged to simplify testing.  In this post, I’ll show you how the decorator pattern is employed to provide simple, pain-free row-level security, ensuring that users can only see projects and issues that they’ve been granted access to.

More...

Tags:

Aug 25 2011

Data Access in Fail Tracker–Unit Testing

Category: SpecsFor | Testing | Fail TrackerMatt @ 14:15

In my last post, I described Fail Tracker’s simple repository model for abstracting LINQ to NHibernate, which is used for all data access in Fail Tracker.  One reason I chose to implement an abstraction around NHibernate’s ISession interface was to facilitate Test Driven Development, a practice that wasn’t really feasible given how LINQ to NHibernate is implemented as an unmockable extension method.  While the abstraction made data access mockable, it would still have been painful if it weren’t for a base SpecsFor context that handled all the heavy lifting. 

More...

Tags:

Aug 2 2011

Data Access in Fail Tracker

Category: NHibernate | Fail TrackerMatt @ 16:21

This is going to be the first in a series of short posts on how data access is handled in Fail Tracker.  Future posts will get into how the strategy works with unit testing as well as how advanced topics, such as row-level security, are handled.  Read on to find out how Fail Tracker utilizes a simple repository layer around NHibernate for all data access.

More...

Tags:

Jul 7 2011

Cleaning up POSTs in ASP.NET MVC, the Fail Tracker Way

Category: Fail Tracker | MVC | ASP.NETMatt @ 12:36

Those who have worked with ASP.NET MVC for more than a day have no doubt found themselves repeating common patterns when handling POSTs.  Jimmy Bogard recently blogged one way to simplify your actions.  I handled the same problem in Fail Tracker by implementing a very simple convention (one-model-in, one-model-out) and pushing some responsibility into the application framework.  With this in place, cross-cutting POST handling logic can be pushed out of the action methods, and a common “doh” error (forgetting to perform server-side validation) can be eliminated.  Read on to find out how you can adopt this simple convention in your application framework. 

More...

Tags:

Jul 5 2011

Building Nice Display Names From Pascal-Case View Model Names in ASP.NET MVC 3

Category: ASP.NET | MVC | Fail TrackerMatt @ 12:56

One of my goals with Fail Tracker is to push the “Convention over Configuration” idea as far as you possibly can within the confines of ASP.NET MVC.  I’m obviously biased, but so far I think I’ve been quite successful, and Fail Tracker is probably the most enjoyable codebase I’ve ever worked with.  One convention I recently implemented eliminates the need to decorate view model properties with the DisplayNameAttribute.  The convention says “Pascal cased property names will be intelligently split into strings with spaces.”  Thanks to the infrastructure and pluggable model metadata system that Fail Tracker uses, implementing this convention was quite easy.

By default in ASP.NET MVC 3, a view model like the following:

public class LogOnForm
{
    [Required]
    [EmailAddress]
    public string EmailAddress { get; set; }

    [Required]
    [DataType(DataType.Password)]
    public string Password { get; set; }
}

will generate a field label that looks like this:

image

Note the missing space between “Email” and “Address.”  This is obviously not what we want.  The way I solved it originally was to apply the DisplayNameAttribute to my view model:

public class LogOnForm
{
    [Required]
    [EmailAddress]
    [DisplayName("Email Address")]
    public string EmailAddress { get; set; }

    [Required]
    [DataType(DataType.Password)]
    public string Password { get; set; }
}

which gives the desired UI:

image

But this seemed pointless to me.  Why should I have to remember to de-Pascal case my property names every time I created a view model?  Fortunately, I don’t have to.  Here’s the “model metadata filter” (a feature of the Fail Tracker application framework) that achieves the same thing:

public class PascalCaseToDisplayNameFilter : IModelMetadataFilter
{
    public void TransformMetadata(System.Web.Mvc.ModelMetadata metadata, IEnumerable<Attribute> attributes)
    {
        if (!string.IsNullOrEmpty(metadata.PropertyName) && !attributes.OfType<DisplayNameAttribute>().Any())
        {
            metadata.DisplayName = metadata.PropertyName.ToStringWithSpaces();
        }
    }
}

The ToStringWithSpaces extension method is a beautiful piece of Regex that James Kolpack gets credit for:

public static class StringExtensions
{
     public static string ToStringWithSpaces(this string input)
     {
         return Regex.Replace(
            input,
            "(?<!^)" + // don't match on the first character - never want to place a space here
            "(" +
            "  [A-Z][a-z] |" + // put a space before "Aaaa"
            "  (?<=[a-z])[A-Z] |" + // put a space into "aAAA" before the first capital
            "  (?<![A-Z])[A-Z]$" + // if the last letter is capital, prefix it with a space too
            ")",
            " $1",
            RegexOptions.IgnorePatternWhitespace);
     }
}

And that’s all there is to it.  Thanks to the application framework that is baked into Fail Tracker, simply creating the PascalCaseToDisplayNameFilter is all that’s necessary.  I can now remove most of my DisplayNameAttributes from my view models.  Do note though that the convention is quite easy to override.  If I do need to alter the labeling for a property, I can still use the DisplayNameAttribute exactly as before.  All my convention does is provide a more reasonable default without getting in the way of doing something different, which is exactly what a good convention should do.

If you want to know more about how these sorts of conventions are automagically wired up in Fail Tracker, feel free to check out Fail Tracker code.  I do plan to write much more about the application framework itself, but it may be a while as I’m targeting a magazine publication for that. Smile

Tags: