Tuesday, December 22, 2009

Asp.Net MVC, Forms and Missing Values

Remember, Asp.Net requires that you use the Name and not just ID on your form controls. If you don’t, they don’t come along for the ride to your controller.

Friday, December 4, 2009

RedBox “Verify Your Subscription” Emails

Anytime I get an unsolicited email saying “verify” something, I’m suspicious. I’ve gotten three of these emails lately. Checking the links, they seem to be genuine. I also found this on Facebook, that seems to indicate they are real. Did notice that lady hadn’t been able to use her code.

Think I’ll give it a try and see what happens.

Sunday, November 22, 2009

Cache and Compress in Asp.Net MVC

Found a good entry on caching at the user browser and compressing the response. Note: It’s from some early beta stuff so be sure to change FilterExecutingConext to ActionExecutingContext. More on that here.

Enjoy!

Wednesday, November 18, 2009

Dell Inspiron 1525, Sleep Mode and Magentic Bracelets

File this in the Hmmm category. Apparently Dell uses a magnet for detecting if the lid has been closed. If you (or your wife) is wearing a magnetic bracelet and it gets close to the sensor, your computer will go to sleep. Leading your wife to yell in frustration. I do need to give her credit, she did figure out it was the bracelet.

Friday, October 30, 2009

Silverlight 3 Page Not Found error

I was working on a project when all of the sudden I started getting a “Page Not Found” error. Of course the page is there and it had been working fine. Turns out it was the templates infrastructure hiding the error from me.

When you create a new SL Navigation Application, you’ll find the following in your MainPage.xml.cs.

// If an error occurs during navigation, show an error window
private void ContentFrame_NavigationFailed(object sender, NavigationFailedEventArgs e)
{
    e.Handled = true;
    ChildWindow errorWin = new ErrorWindow(e.Uri);
    errorWin.Show();
}

This nice little piece of code hides the real cause of the error so that all you see is Page Not Found.

Bryant Likes has some code that will give you a better idea of the error.

// If an error occurs during navigation, show an error window
private void ContentFrame_NavigationFailed(object sender, NavigationFailedEventArgs e)
{
    Exception ex = e.Exception;

    while (ex.InnerException != null)
    {
        ex = ex.InnerException;
    }

    e.Handled = true;
    ChildWindow errorWin = new ErrorWindow(ex);
    errorWin.Show();
}

This should save a few hours of looking.

Friday, October 16, 2009

Nice Drop Shadow Border in XAML

I was working with Silverlight 3 and created this drop shadow border. Enjoy.

<Style x:Key="DropShadow" TargetType="Border">
    <Setter Property="Background" Value="WhiteSmoke" />
    <Setter Property="CornerRadius" Value="5" />
    <Setter Property="BorderThickness" Value="1,1,4,4" />
    <Setter Property="Margin" Value="10" />
    <Setter Property="Padding" Value="6" />
    <Setter Property="BorderBrush">
        <Setter.Value>
            <LinearGradientBrush>
                <GradientStop Color="#ccc" Offset="0" />
                <GradientStop Color="#ddd" Offset="1" />
            </LinearGradientBrush>
        </Setter.Value>
    </Setter>
</Style>

Thursday, October 1, 2009

Using Interfaces, Generics and the Repository Pattern

I’ve been using the repository pattern to insulate my apps from the LINQ to SQL so that I can easily change when (or if) MS kills L2S. The nice thing about this is that I can write a generic repository the encompasses some of the tasks so that the code is consistent for all repositories.

A little background first. We name all our tables the plural of the objects contained and the first column is an integer primary key named in the singular followed by a “Key” suffix. For example, the Customers table has a first column of CustomerKey. This key name is then used in all related tables as the foreign key column. This makes it very easy to come in behind someone and figure out the data structure.

This convention gets in the way of making life easier for me because all items have a different name for the primary key. To fix this, created an interface called IPrimaryKey, shown below.

public interface IPrimaryKey
{
    int PrimaryKey { get; set; }
}

In my database model, I change the name from CustomerKey to PrimaryKey.

image  image

I then create an interface for Customer and a partial class implementing the ICustomer interface. Note that ICustomer adds IPrimaryKey, so any class implementing ICustomer will also have a PrimaryKey.

public interface ICustomer
     :IPrimaryKey
{
     string FirstName { get; set; }
     string LastName { get; set; }
     string Address { get; set; }
     string City { get; set; }
}

partial class Customer
     : ICustomer
{
}

I can now create an interface for my repository and a generic base class that can be inherited by all my other repositories. Creating an interface allows me to use InversionOfConrol to keep my classes flexible, especially for testing.

public interface IRepository<T> where T : IPrimaryKey
{    
    T GetByKey(int key);    

    void Save(T entity);
}

public abstract class RepositoryBase<T>
    : IRepository<T> where T : IPrimaryKey
{    
    protected BogusDbDataContext dc;
    protected IQueryable<T> SourceTable;    

    public T GetByKey(int key)
    {
        return (from x in SourceTable
                where x.PrimaryKey == key                
                select x).SingleOrDefault();    
    }    

    public IQueryable<T> List()    
    {        
        return from x in SourceTable select x;    
    }    

    public abstract void Save(T entity);
}

And finally here is my customers repository.

public class CustomersRepository
    : RepositoryBase<ICustomer>, ICustomersRepository
{
    public CustomersRepository()
    {
        dc = new BogusDbDataContext();
        SourceTable = dc.Customers;
    }

    public override void Save(ICustomer entity)
    {
        dc.Customers.InsertOnSubmit((Customer)entity);
    }
}

Notice that customers has no code to retrieve an entity by it’s primary key. That code exists in RepositoryBase. All my other repositories can use the same code.

Here is a mock repository and some tests to see how it all fits together.

public class CustomersRepositoryMock
    : RepositoryBase<ICustomer>, ICustomersRepository
{
    private List<ICustomer> customers;

    public CustomersRepositoryMock()
    {
        customers = new List<ICustomer>();

        customers.Add(new Customer() { PrimaryKey = 1, FirstName = "John", LastName = "Public", Address = "123 Main", City = "Somewhereville" });
        customers.Add(new Customer() { PrimaryKey = 2, FirstName = "Larry", LastName = "Jones", Address = "456 Oak", City = "Somewhereville" });
        customers.Add(new Customer() { PrimaryKey = 3, FirstName = "Fred", LastName = "Smith", Address = "789 Grand", City = "Somewhereville" });
        customers.Add(new Customer() { PrimaryKey = 4, FirstName = "Barb", LastName = "Johnson", Address = "1234 Cedar", City = "Somewhereville" });

        this.SourceTable = customers.AsQueryable();
    }

    public override void Save(ICustomer entity)
    {

    }
}
[TestMethod()]
public void GetByKeyTest()
{
    CustomersRepositoryMock repository = new CustomersRepositoryMock();
    int key = 3;
    ICustomer target = repository.GetByKey(key);

    Assert.AreEqual(key, target.PrimaryKey);
}

[TestMethod()]
public void ListTest()
{
    CustomersRepositoryMock repository = new CustomersRepositoryMock();
    IQueryable<ICustomer> target = 
        from x in repository.List()
            where x.LastName.StartsWith("J")
            orderby x.LastName
            select x;

    Assert.AreEqual(2, target.Count());
    Assert.AreEqual("Johnson", target.First().LastName);
    Assert.AreEqual("Jones", target.Last().LastName);
}
The L2S data context needs to be handled appropriately. I treat the repositories as a unit of work in that I dispose of them almost immediately after use. In this way, I don’t get in trouble with load options. I also try to make sure that I return concrete objects except where I use IQueryable methods. This prevents unwanted problems with a data context that no longer exists.

There are other interfaces that can be used such as one for Beginning / Ending dates and IsActive. Again, write the code in RepositoryBase and all the derived repositories can use the same code.

Thursday, September 3, 2009

Black Screen Of Death (KSOD) and a possible cause

I’ve run into my second instance of a KSOD (black screen with mouse pointer and nothing else). Both are laptops and both had similar circumstances. User closed lid and attempted to restart on the next day. Both got Windows started but then encountered problems, shutdown and met the KSOD.

Theory: I believe what is happening is that the user has the system set to hibernate on the lid closing. This hibernation is occurring when an automated Windows update is in progress. The update then fails because of the hibernation and corrupts the system. Both systems get to CRCDISK.SYS and then die.

The only solution I’ve found is to reimage or reinstall. I tried all of the registry changes, sticky keys and booting from another source. No luck.

Solution: Upgrade to Win7, turn hibernate off and teach users to shutdown.

Friday, July 31, 2009

Jquery for Select All Checkbox

A very common interface is a list of items with a checkbox to select each and them you perform an action on those selected. Typically you have a checkbox at the top to toggle all of the list. This script will take care of everything for you. You can exclude elements by checking the ID or name properties.

$(document).ready(function() {
$("#selectAllCheckBox").click(function() {
var checked_status = this.checked;
$("input[type=CheckBox]").each(function() {
if (this.id != "pleaseSkipMe") {
this.checked = checked_status;
}
});
});
});

Friday, July 24, 2009

Ajax Call Issue

When making an Ajax call, remember to make sure that your target element can accept the result of your call. For example, if I return a string from my call to a target element of <p>, everything is fine. Replace that with a table and you’ll get the lovely message “htmlfile: Unknown runtime error”. Change to a <div> and everything is fine.

Thursday, July 23, 2009

Asp.Net MVC Unit Testing Authorization

Asp.Net provides the Authorize attribute for checking to make sure you have an authenticated user and that they are in the correct role(s). Since this is part of the framework, I don’t need to test the attribute (that’s Microsoft’s job). I do want to test that I have applied the attribute with the correct properties.

Here’s my unit test code for checking that the attribute has been applied.

[TestMethod()]
public void Autorization_Attributes_Have_Been_Applied()
{

MethodInfo[] methodInfos = typeof(CustomersController).GetMethods(BindingFlags.Public |
BindingFlags.Static);

foreach (MethodInfo methodInfo in methodInfos)
{
ParameterInfo[] parmInfo = methodInfo.GetParameters();
if (methodInfo.Name == "Create" | methodInfo.Name == "Edit")
{
var attributes = methodInfo.GetCustomAttributes(typeof(AuthorizeAttribute), true);
Assert.IsNotNull(attributes);
Assert.AreEqual(1, attributes.Length);
var authorizeAttribute = (AuthorizeAttribute)attributes[0];
Assert.IsTrue(authorizeAttribute.Roles.Contains(ApplicationRoles.ChangeCustomersGroup));
}

if (methodInfo.Name == "Index")
{
var attributes = methodInfo.GetCustomAttributes(typeof(AuthorizeAttribute), true);
Assert.IsNotNull(attributes);
Assert.AreEqual(1, attributes.Length);
var authorizeAttribute = (AuthorizeAttribute)attributes[0];
Assert.IsTrue(authorizeAttribute.Roles.Contains(ApplicationRoles.ViewCustomersGroup));
}
}
}
Depending on how much you need to test, you can make sure that only specific roles are applied, etc. My sample above only checks for the Index, Create and Edit methods and allows all others to fall through. You could make it fail so that any public method that wasn’t checked failed the test. Remember, if it’s public on your controller it can be called.



Update: April 1, 2010 -- Josh has taken this to the next step. Check it out here.

UpdateModel Unit Testing Gotcha!

If you’re unit testing and make a call to UpdateModel, you get the case where your object doesn’t get updated.

Say your controller has an Edit Post action similar to:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Customer customer)
{
Customer _customer = repository.GetByKey(customer.CustomerKey);
UpdateModel(_customer);
repository.Save();
return RedirectToAction("Index");
}
Now you might think that the call to UpdateModel will use your the object you passed in. Wrong! It wants the form values that get passed as part of the post request. So if you’re unit testing and using MVC fakes, you need to pass in some form values.
Customer customer = new Customer()
{
CustomerKey = 1234,
CustomerName = "ABC Siding",
Address = "1 Main",
City = "Springfield",
State = "IL",
ZipCode = "62701",
FirstName = "Fred",
LastName = "Jones",
Phone = "2175551212",
Fax = "2175551213",
IsActive = true
};

NameValueCollection formParams = new NameValueCollection {
{ "CustomerName", customer.CustomerName },
{ "Address", customer.Address },
{ "City", customer.City },
{ "State", customer.State },
{ "ZipCode", customer.ZipCode },
{ "FirstName", customer.FirstName },
{ "LastName", customer.LastName },
{ "Phone", customer.Phone },
{ "Fax", customer.Fax },
{ "IsActive", customer.IsActive.ToString() }
};

target.ControllerContext = new FakeControllerContext(
target, "PaulBrown", new string[] { ApplicationRoles.ViewCustomersGroup },
null, formParams, null, null, null);
Once you pass in the form vars, everything works fine. Now the question I’m asking myself is why I’ve got an argument in the method signature at all. The answer is because that was how Scott Gu did it in NerdDinner. Gonna have to look at that!

Wednesday, July 22, 2009

Fake HttpResponse for Asp.Net MVC

Here’s an HttpResponse fake to go with Stephen Walther’s MVC Fakes. It’s based on his HttpRequest. If you need something for testing the cache, look here.

public class FakeHttpResponse
: HttpResponseBase
{
private HttpCookieCollection _cookies;
private NameValueCollection _headers;
private bool isClientConnected;
private bool isRequestBeingRedirected;
private TextWriter output;
private Stream outputStream;

public FakeHttpResponse(
NameValueCollection headers,
HttpCookieCollection cookies
)
{
this._headers = headers;
this._cookies = cookies;
}

public FakeHttpResponse(
NameValueCollection headers,
HttpCookieCollection cookies,
bool isClientConnected,
bool isRequestBeingRedirected,
TextWriter output,
Stream outputStream
)
{
this._headers = headers;
this._cookies = cookies;
this.isClientConnected = isClientConnected;
this.isRequestBeingRedirected = isRequestBeingRedirected;
this.output = output;
this.outputStream = outputStream;
}

public override HttpCookieCollection Cookies
{
get
{
if (this._cookies == null) { this._cookies = new HttpCookieCollection(); }
return this._cookies;
}
}

public override NameValueCollection Headers
{
get
{
if (this._headers == null) { this._headers = new NameValueCollection(); }
return this._headers;
}
}

public override bool Buffer { get; set; }

public override bool BufferOutput { get; set; }

public override string Charset { get; set; }
public override Encoding ContentEncoding { get; set; }
public override string ContentType { get; set; }
public override int Expires { get; set; }
public override DateTime ExpiresAbsolute { get; set; }
public override Stream Filter { get; set; }
public override Encoding HeaderEncoding { get; set; }
public override bool IsClientConnected { get {return isClientConnected;} }
public override bool IsRequestBeingRedirected { get {return isRequestBeingRedirected;} }
public override TextWriter Output { get {return output;} }
public override Stream OutputStream { get {return outputStream;} }
public override string RedirectLocation { get; set; }
public override string Status { get; set; }
public override int StatusCode { get; set; }
public override string StatusDescription { get; set; }
public override int SubStatusCode { get; set; }
public override bool SuppressContent { get; set; }
public override bool TrySkipIisCustomErrors { get; set; }
}

Tuesday, July 21, 2009

Unit Testing Asp.net MVC and the Cache

If you haven’t worked with Stephen Walthers MVC Tip #12, you’re missing out on a great way to test your MVC controllers. He provides fakes for the ControllerContext, HttpContext, HttpRequest, SessionState and also mechanisms for testing authorization. You can download his code at the end of the post.

I created a new project called MvcFakesForTesting and copied all of the classes. I did this so I can extend and grow the project. Stephen wrote his library with pre-release code, so I needed to change a couple of IController references to ControllerBase. I also created added Headers so that I can fake the request headers. Just implement this the same as QueryString and FormParams. Now I have the DLL that I will use on all of our projects for testing. I made sure to include a reference to Stephen so that credit is given where credit is due.

One thing that is not included is a fake for the Cache. Of course, I ran into this on my first test! First of all, the Cache object is sealed / notinheritable and doesn’t have an interface so mocking or faking it is not going to work. We’re going to need a wrapper.

Step one is to create an interface so I can create use dependency injection for testing. ICacheWrapper is simply all of the public methods from Cache.

public interface ICacheWrapper
{
int Count { get; }

object this[string key] { get; set; }

object Add(string key,
object value,
CacheDependency dependencies,
DateTime absoluteExpiration,
TimeSpan slidingExpiration,
CacheItemPriority priority,
CacheItemRemovedCallback onRemoveCallback);

object Get(string key);

void Insert(string key, object value);

void Insert(string key, object value, CacheDependency dependencies);

void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration);

void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemUpdateCallback onUpdateCallback);

void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback);

object Remove(string key);
}

Now I can create  CacheWrapper that implements ICacheWrapper and defers the call to the actual cache.

public class CacheWrapper : ICacheWrapper
{
private Cache cache;

public CacheWrapper()
{
this.cache = HttpContext.Current.Cache;
}

public CacheWrapper(Cache cache)
{
this.cache = cache;
}

#region ICacheWrapper Members

public int Count
{
get { return this.cache.Count; }
}

public object this[string key]
{
get
{
return this.cache[key];
}
set
{
this.cache.Insert(key, value);
}
}

public object Add(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback)
{
return this.cache.Add(key, value, dependencies, absoluteExpiration, slidingExpiration, priority, onRemoveCallback);
}

public object Get(string key)
{
return this.cache[key];
}

public void Insert(string key, object value)
{
this.cache.Insert(key, value);
}

public void Insert(string key, object value, CacheDependency dependencies)
{
this.cache.Insert(key, value, dependencies);
}

public void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration)
{
this.cache.Insert(key, value, dependencies, absoluteExpiration, slidingExpiration);
}

public void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemUpdateCallback onUpdateCallback)
{
this.cache.Insert(key, value, dependencies, absoluteExpiration, slidingExpiration, onUpdateCallback);
}

public void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback)
{
this.cache.Insert(key, value, dependencies, absoluteExpiration, slidingExpiration, priority, onRemoveCallback);
}

public object Remove(string key)
{
return this.cache.Remove(key);
}

#endregion
}

Now, anywhere I want to access the cache, I create a link to ICacheWrapper and provide a mechanism for injecting the wrapper. This makes the code the same whether I’m testing for production.

public class CustomersProxy
{
private ICacheWrapper cache;
private ICustomersRepository repository;

public CustomersProxy(ICustomersRepository repository, ICacheWrapper cache)
{
this.repository = repository;
this.cache = cache;
}

public List<Customer> ListCustomers()
{
List<Customer> customers = (List<Customer>)this.cache[CustomersCacheKey];
if (customers == null)
{
customers = repository.FindAll();
this.cache.Add(
CustomersCacheKey,
customers ,
null,
Cache.NoAbsoluteExpiration,
new TimeSpan(1, 0, 0),
CacheItemPriority.AboveNormal,
null);
}
return customers;
}
}

FakeCacheWrapper uses a Dictionary to act as the cache. It implements ICacheWrapper so we can inject it for testing anywhere we need to call the cache.

public class FakeCacheWrapper : ICacheWrapper
{
private readonly Dictionary<string, object> cacheItems;

public static readonly DateTime NoAbsoluteExpiration;

public static readonly TimeSpan NoSlidingExpiration;

public FakeCacheWrapper()
{
this.cacheItems = new Dictionary<string, object>();
}

public int Count { get { return this.cacheItems.Count; } }

public object this[string key]
{
get
{
return Get(key);
}
set
{
cacheItems.Add(key, value);
}
}

public object Add(string key,
object value,
CacheDependency dependencies,
DateTime absoluteExpiration,
TimeSpan slidingExpiration,
CacheItemPriority priority,
CacheItemRemovedCallback onRemoveCallback)
{
this.cacheItems.Add(key, value);
return value;
}

public object Get(string key)
{
if (this.cacheItems.ContainsKey(key))
{ return this.cacheItems[key]; }
return null;
}

public IDictionaryEnumerator GetEnumerator()
{ return this.cacheItems.GetEnumerator(); }

public void Insert(string key, object value)
{
this.cacheItems.Add(key, value);
}

public void Insert(string key, object value, CacheDependency dependencies)
{
this.cacheItems.Add(key, value);
}

public void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration)
{
this.cacheItems.Add(key, value);
}

public void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemUpdateCallback onUpdateCallback)
{
this.cacheItems.Add(key, value);
}

public void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback)
{
this.cacheItems.Add(key, value);
}

public object Remove(string key)
{
object obj = null;
if (this.cacheItems.ContainsKey(key))
{
obj = this.cacheItems[key];
}
this.cacheItems.Remove(key);
return obj;
}
}
Now my controller has an two constructors, one for production and one for testing.
public class CustomersController : Controller
{
private CustomersProxy proxy;

public CustomersController()
{
CacheWrapper wrapper = new CacheWrapper(HttpContext.Current.Cache);
CustomersRepository repository = new CustomersRepository();
this.proxy = new CustomersProxy(repository, wrapper);
}

public CustomersController(CustomersProxy proxy)
{
this.proxy = proxy;
}

.....
}

With Stephen’s fakes and ICacheWrapper/FakeCacheWrapper, I can now test just about everything I need to.

Friday, July 17, 2009

KVM Switch gives USB not recognized

My TrendNet TK409K KVM popped up with a “USB not recognized or malfunctioned” today. The solution I found was to unplug all of the USB connections for a minute. This apparently “resets” the box. Plug everything back in and away you go.

Wednesday, July 15, 2009

Make Internal Methods Visible for Unit Testing

Need to make your internal classes and methods visible to unit testing? Try the post. Works like a champ!

Tuesday, July 14, 2009

T-SQL to create an instance of an object with the properties set

Here’s some T-SQL to create a SELECT statement that will create the properties with values. I use this for generating test data from existing DB’s. Right now I’ve got it setup to handle int, char, varchar, smalldatetime, datetime and bit. I’ll add others as needed.

@TableName is the name of the table where the data is stored. Simply set the table name hit F5 then cut and paste the generated script into the T-SQL that gets the data your looking for. This can be all rows in the table or a single row.

The code:

declare @TableName varchar(100)
declare @ColumnName varchar(100)
declare @DataType varchar(100)
declare @Sql varchar(max)

declare @Crlf char(2)

set @TableName = 'Clients'
set @Sql = CHAR(39)

declare cols_temp cursor for
SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE Table_Name = @TableName
and data_type in ('int', 'char', 'varchar', 'smalldatetime', 'datetime', 'bit')

open cols_temp

FETCH NEXT FROM cols_temp INTO @ColumnName,@DataType

WHILE @@FETCH_STATUS = 0
BEGIN
IF LEN(@Sql) > 1
SET @Sql = @Sql + ' + ' + CHAR(39) + ', '

IF @DataType = 'int'
SET @Sql = @Sql + @ColumnName + ' = ' + CHAR(39) + ' + CAST(' + @ColumnName + ' As varchar)'

IF @DataType in ('char', 'varchar')
SET @Sql = @Sql + @ColumnName + ' = "' + CHAR(39) + ' + COALESCE(' + @ColumnName + ', '''') + ' + CHAR(39) + '"' + CHAR(39)

IF @DataType = 'bit'
SET @Sql = @Sql + @ColumnName + ' = '' + CASE WHEN ' + @ColumnName + '=1 THEN ''true'' ELSE ''false'' END'

IF @DataType = 'smalldatetime'
SET @Sql = @Sql + @ColumnName + ' = new DateTime('' + CAST(YEAR(' + @ColumnName + ') As varchar) + '', '' + CAST(MONTH(' + @ColumnName + ') As varchar) + '', '' + CAST(DAY(' + @ColumnName + ') As varchar) + '', 0, 0, 0)'''

IF @DataType = 'datetime'
SET @Sql = @Sql + @ColumnName + ' = new DateTime('' + CAST(YEAR(' + @ColumnName + ') As varchar) + '', '' + CAST(MONTH(' + @ColumnName + ') As varchar) + '', '' + CAST(DAY(' + @ColumnName + ') As varchar) + '', '' + CAST(DATEPART(HH,' + @ColumnName + ') As varchar) + '', '' + CAST(DATEPART(N,' + @ColumnName + ') As varchar) + '', '' + CAST(DATEPART(S,' + @ColumnName + ') As varchar) + '')'''

FETCH NEXT FROM cols_temp INTO @ColumnName,@DataType
END

SELECT @Sql

close cols_temp

deallocate cols_temp

Sample uses to add to rows to a collection:

SELECT 
'clientsCollection.Add(new Client() {ClientKey = ' + CAST(ClientKey As varchar)
+ ', FirstName = "' + COALESCE(FirstName, '') + '"'
+ ', LastName = "' + COALESCE(LastName, '') + '"'
+ ', MiddleInitial = "' + COALESCE(MiddleInitial, '') + '"'
+ ', Birth = new DateTime(' + CAST(YEAR(Birth) As varchar)
+ ', ' + CAST(MONTH(Birth) As varchar)
+ ', ' + CAST(DAY(Birth) As varchar) + ', 0, 0, 0) });'
FROM Clients
This generates the following:
clientsCollection.Add(new Client() { ClientKey = 52, FirstName = "Paul", LastName = "McCartney", MiddleInitial = "", Birth = new DateTime(1945, 10, 15, 0, 0, 0) });
clientsCollection.Add(new Client() { ClientKey = 43, FirstName = "George", LastName = "Harrison", MiddleInitial = "D", Birth = new DateTime(1943, 12, 17, 0, 0, 0) });
clientsCollection.Add(new Client() { ClientKey = 84, FirstName = "Ringo", LastName = "Starr", MiddleInitial = "A", Birth = new DateTime(1949, 12, 5, 0, 0, 0) });
Sample to create a specific instance:
SELECT 
'Client testClient = new Client() {ClientKey = ' + CAST(ClientKey As varchar) + ', FirstName = "' + COALESCE(FirstName, '') + '"' + ', LastName = "' + COALESCE(LastName, '') + '"' + ', MiddleInitial = "' + COALESCE(MiddleInitial, '') + '"' + ', Birth = new DateTime(' + CAST(YEAR(Birth) As varchar) + ', ' + CAST(MONTH(Birth) As varchar) + ', ' + CAST(DAY(Birth) As varchar) + ', 0, 0, 0) });'
FROM Clients
WHERE ClientKey = 52
This generates the following (I formatted the code):
Client testClient = new Client() {
ClientKey = 52,
FirstName = "Paul",
LastName = "McCartney",
MiddleInitial = "",
Birth = new DateTime(1945, 10, 15, 0, 0, 0)
};
Have fun!!!

Thursday, July 2, 2009

What’s in a name?

I’ve worked on database projects for over 20 years. I go back to FoxBASE and dBase. I’ve also been through a number of naming conventions in that time. I’ve developed a personal preference but can work with other preferences because I can usually figure them out fairly quickly.

Here’s two rules I use as part of my database designs:

  1. Use a surrogate or artificial key as the primary key to avoid the need for cascading deletes or updates.
  2. Use the natural name for each element so that elements are easily identifiable when in discussions with the user.

I can’t tell you how much time I have saved over the years with rule 2. Users have no idea of your database design (and they shouldn’t!) but they know exactly which piece of information they want. It’s a whole lot easier if they can write “client’s birth date” in a report request and in the Clients table there is a field called BirthDate.

My problem is lately, I’ve noticed that a lot of people seem to be using a convention that drives me nuts - the use of ElementNameID as the primary key. This is the standard in a lot of the Microsoft examples.

What's the big deal? In one of our systems we have a table named Clients that holds…wait for it..a client. That client has an ID that is assigned from a legacy mainframe system and of course it’s called ClientID. This element has become a part of the users culture and is used to identify clients and it’s natural name is Client ID in user discussions.

“So just make it your primary key and you’re fine.” Not so fast. Remember, this is coming from a legacy system, in this case a 25 year old system. In those days disk space was expensive and you squeezed everything you could into a field. Specifically, the first 6 positions are the family group and the last two differentiate between individuals.

My problem here is that since the value has internal meaning, someone, somewhere will want to change this value. For this reason, I always use artificial or surrogate keys (see rule 1). No worries about cascading updates or orphaned rows.

Ok, so now my clients will have two values named ClientID. One the actual key and the other a legacy key. I could use an underscore for one, i.e. Client_ID. I could simply rename the legacy value ClientIDLegacy. Either one means that everyone who looks at my data will have to figure out what I did.

Worse, the natural name and the database name are different, violating rule 2. I could use Client_ID for the key instead but that means I need to change all of my other tables to match or live with the inconsistency (meaning remember to use the underscore on this one table).

My solution? It’s very simple, ClientKey. The element we are describing is a key and not an ID. To me, ID (or identifier) is something to be consumed by humans. Keys are for systems. I really can’t remember something being called “key” in a non-IT environment.

It may seem trivial, but I can think of half a dozen cases of the top of my head where you’ll run into this. It may not get you on this system but how about the next one? Now you have two systems with two different conventions. Now you need to remember what you did in one and not in the other. After 20 years, I’m limiting what I need to remember only to those things I can’t control <g>!

Thursday, June 18, 2009

Asp.Net Forms Authentication with Groups and Roles

I found this great post from Rob Convery on creating a FilterAttribute that can be used to authorize specific controller actions against roles. I’d always wanted to implement a Group strategy and had made several attempts. They all seemed like kluges and I was never really happy.

One small change to Rob’s code and I can do grouping in a simple manner. Note: If you have a large number of roles and groups, this will probably not work for you. Also, this uses Asp.Net MVC.

ok, Rob’s code basically checked for a single role and you could use a constant to supply the role name. Something like

[RequiresRoleAttribute(RoleToCheckFor = ApplicationRoles.AdminRole)]
public ActionResult Edit(int id)

My change just allows you to pass more than one role into RoleToCheckFor.  Basically, I split RoleToCheckFor using a comma.

[RequiresRoleAttribute(RoleToCheckFor = ApplicationRoles.ChangeClientsGroup)]
public ActionResult Edit(int id)
The ApplicationRoles class looks like this.
public class ApplicationRoles
{
public const string AdminRole = "Admin";
public const string EntryRole = "Entry";
public const string ManagementRole = "Management";
public const string SecurityRole = "Security";

public const string ChangeClientsGroup = Admin + "," + Entry;
}

ChangeClientsGroup is simply a constant that contains all the allowed roles for changing clients. Biggest drawback here, I want to change a group, I need to redeploy. This isn’t really a problem since I don’t have to change my roles a lot but…
public class RequiresRoleAttribute : ActionFilterAttribute
{
public string RoleToCheckFor { get; set; }

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//redirect if the user is not authenticated
if (!String.IsNullOrEmpty(RoleToCheckFor))
{

if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{

//use the current url for the redirect
string redirectOnSuccess = filterContext.HttpContext.Request.Url.AbsolutePath;

//send them off to the login page
string redirectUrl = string.Format("?ReturnUrl={0}", redirectOnSuccess);
string loginUrl = FormsAuthentication.LoginUrl + redirectUrl;
filterContext.HttpContext.Response.Redirect(loginUrl, true);

}
else
{
bool isAuthorized = false;
string[] roles = this.RoleToCheckFor.Replace(" ", string.Empty).Split(',');
foreach (string role in roles)
{
isAuthorized = filterContext.HttpContext.User.IsInRole(role);
if (isAuthorized) { break; }
}
if (!isAuthorized)
{
ApplicationError appEevent = new ApplicationError();
appEevent.Caller = Thread.CurrentPrincipal.Identity.Name + ":" + filterContext.Controller.GetType().Name + ":" + filterContext.HttpContext.Request.Path;
appEevent.ErrorMessage = "Unauthorized access attempt";
ApplicationManager.RecordEvent(appEevent);
FormsAuthentication.SignOut();
filterContext.HttpContext.Response.Redirect("/SecurityViolation.htm", true);
}
}
}
else
{
throw new InvalidOperationException("No Role Specified");
}
}
}

Hopes this works for you!

Tuesday, May 12, 2009

T-SQL To Identify All Characters in a Column

When doing conversions, I often need to write a RegEx pattern for a column. This little query gets all the characters in a string.

declare @ColName varchar(200) = 'Vin'
declare @TblName varchar(200) = 'Units'
declare @sql varchar(max)
declare @maxlength int
declare @iterator int = 1

select @maxlength = c.CHARACTER_MAXIMUM_LENGTH from INFORMATION_SCHEMA.COLUMNS c
where COLUMN_NAME = @ColName

create table #allchars
(
colchar CHAR(1)
)

while @iterator < @maxlength
begin
set @sql = 'insert into #allchars select distinct SUBSTRING(' + @ColName + ', ' + CAST(@iterator as varchar) + ', 1) from ' + @TblName
exec (@sql)
set @iterator = @iterator + 1
end
select distinct colchar from #allchars order by colchar

drop table #allchars
It’s not optimzed cause it just does what I want. Enjoy!

Monday, April 27, 2009

An Asp.Net Validation Framework (Part 3)

An Asp.Net Validation Framework (Part 1)

An Asp.Net Validation Framework (Part 2)

Unfortunately, if you’re using LINQ to SQL or the Entity Framework, you can’t add the custom attributes we need for validation. You could generate your entity model and then simply use those generated objects but you would lose the ability to use the designers. I prefer to leverage the code we’ve written.

public class ValidatableOrmBase
: ValidatableBase
{

private List<CustomPropertyAttributeListItem> customPropertyAttributes;

public List<CustomPropertyAttributeListItem> CustomPropertyAttributes
{
get
{
if (customPropertyAttributes == null)
{
customPropertyAttributes = new List<CustomPropertyAttributeListItem>();
}
return customPropertyAttributes;
}
}

public override bool Validate(bool clearBrokenRules)
{
base.Validate(clearBrokenRules);
foreach (CustomPropertyAttributeListItem cvli in CustomPropertyAttributes)
{
PropertyInfo theProperty = this.GetType().GetProperty(cvli.PropertyName, BindingFlags.Public | BindingFlags.Instance);
if (!cvli.CustomAttribute.IsValid(theProperty.GetValue(this, null), cvli.PropertyName))
{
BrokenRules.Add(cvli.CustomAttribute.Rule);
}
}

return BrokenRules.Count == 0;
}
}
public class CustomPropertyAttributeListItem
{
public string PropertyName { get; set; }

public ValidationAttribute CustomAttribute { get; set; }
}

All we’ve done here is create a subclass of ValidatableBase that has a CustomPropertyAttributes property of type List<CustomPropertyAttributeListItem>. Basically, we’re building a list of attributes and the the property to which they need to be applied. Validate is then overridden to call the base (just in case there are attributes) and the loop through the list.

This technique uses exactly the same code for validation, our public interface stays the same (in case they change things so we can add attributes) and we haven’t sacrificed anything from an extensibility perspective.

partial class MyLinqToSqlClass    
: ValidatableOrmBase
{
public MyLinqToSqlClass()
: base()
{
this.CustomPropertyAttributes.Add(
new CustomPropertyAttributeListItem() {
PropertyName = "FirstName",
CustomAttribute = new RequiredAttribute() {
DisplayName = "first name" } }); }
}

Now to implement, we simply create our partial class and inherit from ValidatableOrmBase. Ok, we’re all done. Wait! You can’t use the partial class on EF entities since they already inherit from another class. Rats!!!!! Don’t fret, there is a way to accomplish our goals.

First, let’s create a new base class that implements IValidatable.

public class ValidatableEfBase
: IValidatable
{

/// <summary>
/// Holds the collection of broken business rules.
/// </summary>
private BrokenRulesCollection brokenRules;

private List<CustomPropertyAttributeListItem> customPropertyAttributes;

/// <summary>
/// Gets the collection of business rules that have
/// been broken.
/// </summary>
public BrokenRulesCollection BrokenRules
{
get
{
if (this.brokenRules == null)
{
this.brokenRules = new BrokenRulesCollection();
}
return this.brokenRules;
}
}

public List<CustomPropertyAttributeListItem> CustomPropertyAttributes
{
get
{
if (customPropertyAttributes == null)
{
customPropertyAttributes = new List<CustomPropertyAttributeListItem>();
}
return customPropertyAttributes;
}
}

public EntityObject Entity { get; set; }

/// <summary>
/// Validates the objects.
/// </summary>
/// <returns>True if the object is valid, otherwise false.</returns>
public bool Validate(bool clearBrokenRules)
{
if (clearBrokenRules)
{
this.BrokenRules.Clear();
}

foreach (CustomPropertyAttributeListItem cvli in CustomPropertyAttributes)
{
PropertyInfo theProperty = Entity.GetType().GetProperty(cvli.PropertyName, BindingFlags.Public | BindingFlags.Instance);
if (!cvli.CustomAttribute.IsValid(theProperty.GetValue(Entity, null), cvli.PropertyName))
{
BrokenRules.Add(cvli.CustomAttribute.Rule);
}
}

return BrokenRules.Count == 0;
}
}

Ok, we have all our functionality and it’s centrally located. Now, how do we expose it. Simple, we use partial classes and defer the validation to an instance of the above. Like so.

public partial class MyEFEntity
: IValidatable
{
public BrokenRulesCollection BrokenRules
{
get
{
return validator.BrokenRules;
}
}

private ValidatableEfBase validator;

protected ValidatableEfBase Validator
{
get
{
if (validator == null)
{
validator = new ValidatableEfBase();
validator.Entity = this;
}
return validator;
}
}

public bool Validate(bool clearBrokenRules)
{
CreateCustomAttributes(false);
return Validator.Validate(clearBrokenRules);
}

protected void CreateCustomAttributes(bool clearList)
{
if (clearList)
{
Validator.CustomPropertyAttributes.Clear();
}
Validator.CustomPropertyAttributes.Add(
new CustomPropertyAttributeListItem() { PropertyName = "Name", CustomAttribute = new RequiredAttribute() { DisplayName = "name" } });
}
}

Notice we have BrokenRules and Validate so we’ve met our interface requirements, meaning it looks the same from the outside. This is important for both techniques since we want to be able to change the internal implementation if MS changes things so we can add our attributes.

What happens underneath is simple. The Validator (an instance of ValidatableEfBase) actually performs all the validation on the EF entity.

That wraps up the Validation Framework. Next, I’ll look at how to create a client side validation framework for use with Asp.Net MVC.

Friday, April 10, 2009

Asp.Net MVC and Sys is undefined

If you’ve run into the Sys is undefined message, check to make sure that you’ve included the following:

<script src="<%= Url.Content("~/Scripts/MicrosoftAjax.debug.js") %>" type="text/javascript"></script>
and
<script src="<%= Url.Content("~/Scripts/MicrosoftMvcAjax.debug.js") %>" type="text/javascript"></script>
You can include them in your masterpage or each individual page.

Friday, April 3, 2009

Error 0x80090305 with VSS Internet

I received the above error recently when trying to connect to my VSS server using the internet service. What appears to be causing the error is that I had configured my machine  for FIPS level remote desktop access using this page. As soon as I turned it off, everything worked again.

Monday, March 9, 2009

An Asp.Net Validation Framework (Part 2)

In the first part, we saw how to create custom attributes and rules. Now we'll look at how to implement those attributes.

The IValidatable interface defines how consumers can interact with the framework. It indicates that we'll have a collection of BrokenRules and offers a method to perform validation.

ValidatableBase implements IValidatable and does most of the work. Your classes simply inherit from ValidatableBase and they are completely functional. You decorate all of the properties you want.

/// <summary>
/// Interface for class that wish to implement
/// validation.
/// </summary>
public interface IValidatable
{
    /// <summary>
    /// Gets the collection of business rules that have 
    /// been broken.
    /// </summary>
    BrokenRulesCollection BrokenRules { get; }

    /// <summary>
    /// Validates the objects.
    /// </summary>
    /// <param name="clearBrokenRules">Indicates if the BrokenRules collection
    /// should be cleared of prior to validation.</param>
    /// <returns>True if the object is valid, otherwise false.</returns>
    bool Validate(bool clearBrokenRules);
}

/// <summary>
/// Base class for implementation of validation
/// through attributes.
/// </summary>
public abstract class ValidatableBase
    : IValidatable
{
    /// <summary>
    /// Holds the collection of broken business rules.
    /// </summary>
    private BrokenRulesCollection brokenRules;

    /// <summary>
    /// Initializes a new instance of the ValidatableBase class.
    /// </summary>
    public ValidatableBase()
    {
        this.brokenRules = new BrokenRulesCollection();
    }

    /// <summary>
    /// Gets the collection of business rules that have 
    /// been broken.
    /// </summary>
    public BrokenRulesCollection BrokenRules
    {
        get
        {
            return this.brokenRules;
        }
    }

    /// <summary>
    /// Validates the objects.
    /// </summary>
    /// <returns>True if the object is valid, otherwise false.</returns>
    public virtual bool Validate()
    {
        return this.Validate(true);
    }

    /// <summary>
    /// Validates the objects.
    /// </summary>
    /// <param name="clearBrokenRules">Indicates if the BrokenRules collection
    /// should be cleared of prior to validation.</param>
    /// <returns>True if the object is valid, otherwise false.</returns>
    public virtual bool Validate(bool clearBrokenRules)
    {
        if (clearBrokenRules)
        {
            this.BrokenRules.Clear();
        }

        PropertyInfo[] properties = this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);

        var valProps = from PropertyInfo property in properties
                       where property.GetCustomAttributes(typeof(ValidationAttribute), true).Length > 0
                       select new
                       {
                           Property = property,
                           ValidationAttributes = property.GetCustomAttributes(typeof(ValidationAttribute), true)
                       };

        foreach (var item in valProps)
        {
            foreach (ValidationAttribute attribute in item.ValidationAttributes)
            {
                if (attribute.IsValid(item.Property.GetValue(this, null), item.Property.Name))
                {
                    continue;
                }

                this.BrokenRules.Add(attribute.Rule);
            }
        }

        return this.BrokenRules.Count == 0;
    }
}

So what does it do? Basically, the Validate method iterates through all properties that have at least one ValidationAttribute applied. It then iterates through each property's ValidationAttributes and checks IsValid. If it is false, it adds the Rule from the attribute to the BrokenRules collection. This is all done using reflection.

Here's the my version of BrokenRulesCollection. It uses Collection<> but you could just as easily use a List<>.

/// <summary>
/// Class to hold BrokenRules.
/// </summary>
[Serializable]
public class BrokenRulesCollection
    : Collection<BrokenRule>
{
    /// <summary>
    /// Adds a new BrokenRule to the collection with
    /// the specified property name and error message.
    /// </summary>
    /// <param name="propName">The name of the property that was invalid.</param>
    /// <param name="msg">The error message.</param>
    public void Add(string propName, string msg)
    {
        this.Add(new BrokenRule(propName, msg));
    }
}

Please look at Imar's posts as they really clarified the idea for me.

Next, we’ll look at how to implement this strategy with Linq To Sql and the Entity Framework.

Saturday, March 7, 2009

An Asp.Net Validation Framework

I've been working on different ways to implement a validation framework that would really cut down on the code. It  had to be reusable and testable. I also didn't want to swap writing one bunch of repetitive code for another.

I'd looked at CSLA from Rockford Lhotka. I liked the way he implemented broken rules but CSLA had a lot of stuff for multiple undo's that was not relevant to my apps. I then used some of ScottGu's stuff for LINQ to SQL and begin using validation methods that threw exceptions. Reusable and custom exceptions made this very testable but I was still writing a bunch of repetitive code.

Microsoft's Enterprise Library has a Validation Block that was interesting but really seemed to be overkill.  I did like the declarative nature though and then found this from Imar Spaanjaars. That was more what I was looking for and I could see where I could make some changes.

First change was in the naming. NotNullOrEmptyAttribute became RequiredAttribute and ValidSsnAttribute became SsnAttribute. This seemed to work better for me.

Next was removing the localization. I've never had to write an app for anything but English. I know, next week I'll get one. That's ok, I left some places to hook in if I need to.

The largest change was to how I handle messages. I created a number of attributes to handle common elements like proper names, SSN, phone numbers, etc  (more on these in a later post) and I wanted to be able to do something like below.

[Required(DisplayName="SSN")]
[Ssn]
public string Ssn { get; set; }

Notice on the Ssn attribute there is no message property set. I have used pretty much the same error message for bad SSN's since I can remember. Why do I need to type a message on SSN element? I don't!

Everything starts with the ValidationAttribute class and all custom validation attributes will inherit from this class. Let's look at it.

/// <summary>
/// Base class for validation attributes.
/// </summary>
public abstract class ValidationAttribute
    : System.Attribute
{
    /// <summary>
    /// Initializes a new instance of the ValidationAttribute class.
    /// </summary>
    public ValidationAttribute()
    {
        this.DisplayName = string.Empty;
    }

    /// <summary>
    /// Gets or sets the BrokenRule with the error message.
    /// </summary>
    public BrokenRule Rule { get; set; }

    /// <summary>
    /// Gets or sets the name to be displayed for the element.
    /// </summary>
    public string DisplayName { get; set; }

    /// <summary>
    /// Gets or sets the error message.
    /// </summary>
    public string Message { get; set; }

    /// <summary>
    /// Indicates if the property is valid according to the attribute.
    /// </summary>
    /// <param name="item">The value of the property.</param>
    /// <param name="propName">The name of the property.</param>
    /// <returns>True if the property passes the validation rule, otherwise false.</returns>
    public abstract bool IsValid(object item, string propName);
}

There are three properties and one virtual method. Rule which is of type BrokenRule (more on this in a moment. DisplayName which holds the friendly name of the element. Notice how DisplayName is set to string.Empty in the constructor. Finally, we use Message to customize messages when needed.

The IsValid method checks to see if the element is valid (based on validation code in the subclasses). It accepts the value and name of the property as arguments. The value comes through as an object so that we can apply the attribute to different types. The name is passed because there is no link between the attribute and it's property.

Now we need a class that will actually validate something. The most common validation is required elements so we'll start with the RequiredAttribute.

/// <summary>
/// Attribute for validating that a value is not empty or null.
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public sealed class RequiredAttribute
    : ValidationAttribute
{
    /// <summary>
    /// Initializes a new instance of the RequiredAttribute class.
    /// </summary>
    public RequiredAttribute()
    {
        DisplayName = "value";
    }
    
    /// <summary>
    /// Validates that the string is not empty or null.
    /// </summary>
    /// <param name="item">The string to be validated.</param>
    /// <param name="propName">The name of the invalid property.</param>
    /// <returns>True if the string has a value and is not empty, otherwise false.</returns>
    public override bool IsValid(object item, string propName)
    {
        Rule = new Rules.RequiredRule(propName, DisplayName);
        if (!Message.IsEmpty())
        {
            Rule.Message = Message;
        }

        if (item is string)
        {
            return !string.IsNullOrEmpty(item as string);
        }

        if (item is DateTime)
        {
            if (item == null)
            {
                return false;
            }

            if (Convert.ToDateTime(item) == DateTime.MinValue)
            {
                return false;
            }

            return true;
        }

        if (item is int)
        {
            if (Convert.ToInt32(item) == 0)
            {
                return false;
            }

            return true;
        }

        return item != null;
    }
}

The DisplayName is set to "value" by default but will get overridden if set. Otherwise, the only code is to check if the property actually has a value. Strings, DateTime and ints are all checked. In case you're wondering, IsEmpty is an extension method I wrote that checks if a string is null or empty.

What the Rule property? Well, we create an instance of the RequiredRule and pass the property and display names. RequiredRule is a subclass of BrokenRule with a default message. Here's the code for both.

/// <summary>
/// Simple representation of a broken business rule.
/// </summary>
public class BrokenRule
{
    /// <summary>
    /// Initializes a new instance of the BrokenRule class.
    /// </summary>
    public BrokenRule()
    {
    }

    /// <summary>
    /// Initializes a new instance of the BrokenRule class.
    /// </summary>
    /// <param name="propName">The name of the property that was invalid.</param>
    public BrokenRule(string propName)
    {
        this.PropertyName = propName;
    }

    /// <summary>
    /// Initializes a new instance of the BrokenRule class.
    /// </summary>
    /// <param name="propName">The name of the property that was invalid.</param>
    /// <param name="msg">The error message.</param>
    public BrokenRule(string propName, string msg)
    {
        this.PropertyName = propName;
        this.Message = msg;
    }

    /// <summary>
    /// Gets or sets the name of the property that was invalid.
    /// </summary>
    public string PropertyName { get; set; }

    /// <summary>
    /// Gets or sets the error message.
    /// </summary>
    public string Message { get; set; }
}

/// <summary>
/// Class to represent a broken required field rule.
/// </summary>
public class RequiredRule
    : BrokenRule
{
    /// <summary>
    /// Initializes a new instance of the RequiredRule class.
    /// </summary>
    /// <param name="propName">The name of the property that was invalid.</param>
    /// <param name="dispName">The name to be displayed for the element.</param>
    public RequiredRule(string propName, string dispName)
        : base(propName, string.Format(RuleMessages.RequiredMessage,
        dispName == string.Empty ? propName : dispName))
    {
    }
}

BrokenRule has the property name and the message. RequiredRule simply formats the constant RequiredMessage  with the DisplayName  (or property name if there isn't a DisplayName) and passes it to the base constructor.

You might be asking why not simply use a factory method to get the default message instead of a custom type? The answer is that this allows me to test for specific attributes without having to check all the different messages using Assert.IsInstanceOf.

Assert.IsInstanceOfType(testMock.BrokenRules[0], typeof(RequiredRule));

Assert.IsInstanceOfType(testMock.BrokenRules[0], typeof(SsnRule));
Now my unit tests can check if the Required and Ssn attributes were applied. Testability was just as important as getting rid of the repetitive code.

Next, we'll look at how to get your objects to use these attributes.