3 minute read

I came across this bug last night, which was occurring right as CSLA 4 was released. It had to deal with the CodeSmith CSLA templates when you set UseMemberVariables to true. The error is quite obscure and not very intuitive as the signs of a bug are only found when you check to see if your business object IsValid. The scenario in this case is when you set a required managed property, the rules never fully evaluate the set value. A bunch of other side effects could occur as well. Here is the error you could receive:

CategoryId required

Expected:True

But was:False

Here is the code that was causing the error:

CSharp

protected override void AddBusinessRules()
{
  BusinessRules.AddRule(new Csla.Rules.CommonRules.Required(_categoryIdProperty));
}

private static readonly PropertyInfo<System.String> _categoryIdProperty = RegisterProperty<System.String>(p => p.CategoryId, String.Empty);
private System.String _categoryId = _categoryIdProperty.DefaultValue;
public System.String CategoryId
{
  get { return GetProperty(_categoryIdProperty, _categoryId); }
  set { SetProperty(_categoryIdProperty, ref _categoryId, value); }
}
[Test]
private void CreateCategory(string categoryID)
{
  Category category = Category.NewCategory();
  category.CategoryId = categoryID;
  Assert.IsTrue(category.IsValid, category.BrokenRulesCollection.ToString());
  category = category.Save();
  Assert.IsTrue(category.CategoryId == categoryID);
}

Visual Basic

Protected Overrides Sub AddBusinessRules()
  BusinessRules.AddRule(New Csla.Rules.CommonRules.Required(_categoryIdProperty))
End Sub

Private Shared ReadOnly _categoryIdProperty As PropertyInfo(Of System.String) = RegisterProperty(Of System.String)(Function(p As Category) p.CategoryId, String.Empty)
Private _categoryId As System.String = _categoryIdProperty.DefaultValue
Public Property CategoryId() As System.String

  Get
    Return GetProperty(_categoryIdProperty, _categoryId)
  End Get

  Set (value As System.String)
    SetProperty(_categoryIdProperty, _categoryId, value)

  End Set
End Property

<test()> _
Private Sub CreateCategory(ByVal categoryID As String)
  Dim category As Category = PetShop.Tests.ParameterizedSQL.Category.NewCategory()
  category.CategoryId = categoryID
  Assert.IsTrue(category.IsValid, category.BrokenRulesCollection.ToString())
  category = category.Save()
  Assert.IsTrue(category.CategoryId = categoryID)
End Sub

As you can see the code looks and works fine in CSLA 3.8 but it isn’t the case in 4.0. Once I tracked down what was causing the error, I saw that there wasn’t any checks in CSLA4 to see if the property had the RelationshipTypes.PrivateField overload when you are calling the GetProperty or SetProperty methods with a backing field. The long term fix when using private member backing fields is to set the RelationshipTypes to RelationshipTypes.PrivateField.

CSharp

private static readonly PropertyInfo<System.String> _categoryIdProperty = RegisterProperty<System.String>(p => p.CategoryId, String.Empty, RelationshipTypes.PrivateField);
private System.String _categoryId = _categoryIdProperty.DefaultValue;
public System.String CategoryId
{
  get { return GetProperty(_categoryIdProperty, _categoryId); }
  set { SetProperty(_categoryIdProperty, ref _categoryId, value); }
}

Visual Basic

Private Shared ReadOnly _categoryIdProperty As PropertyInfo(Of System.String) = RegisterProperty(Of System.String)(Function(p As Category) p.CategoryId, String.Empty, RelationshipTypes.PrivateField)
Private _categoryId As System.String = _categoryIdProperty.DefaultValue
Public Property CategoryId() As System.String
  Get
    Return GetProperty(_categoryIdProperty, _categoryId)
  End Get

  Set (value As System.String)
    SetProperty(_categoryIdProperty, _categoryId, value)
  End Set
End Property

This has been fixed in a nightly build of the CodeSmith CSLA Templates and will be in version 3.0.1 of the CodeSmith CSLA Templates. The CSLA team will also be releasing version 4.0.1 of CSLA sometime soon. If you don’t have this overload set in CSLA 4.0.1 then you will receive the following exception:

Properties with private backing fields must be marked as RelationshipTypes.PrivateField

If you are using the CodeSmith CSLA templates, remember to update to the latest templates and regenerate. If you are not, well you should be using the CodeSmith CSLA Templates as it is about to save you a ton of time adding the RelationshipTypes.PrivateField overload to all of your properties!

Join the mailing list

Get notified of new posts and related content to your inbox. I will never sell you anything and I will NEVER sell your email address.