Tips for Building a BO for Silverlight and RIA
The following are some tips when building a business object class for use by Silverlight and RIA services.
NOTE: This assumes you are not using Entity Framework (EF).
Use Class-Level Validation
Specifying class-level validation allows you to perform validation on the entire class. This is a good location for cross-field validation.
For example, say you are creating a Discount class that defines discounts available to your customers. A percentage discount must be less than 100% where a dollar discount can be any amount. In the class-level validation, you can check the discount type against the amount to determine if the fields are valid.
Use the CustomValidation attribute to define class-level validation:
In C#:
[CustomValidation(typeof(DiscountValidation), "ValidateDiscount")]
public class Discount
In VB:
<CustomValidation(GetType(DiscountValidation), "ValidateDiscount")>
Public Class Discount
Define a Key
For WCF RIA Services to recognize your objects, they must have a unique key. In most business objects, this is easy because every object relates to a database row that already has a unique key.
In the above Discount example, the discount already has a unique DiscountId associated with it.
Use the Key attribute to define the key field.
In C#:
private int _DiscountId;
[Key()]
public int DiscountId {
get { return _DiscountId; }
set
{
if (!_DiscountId.Equals(value))
{
// Set the value
_DiscountId = value;
}
}
}
In VB:
Private _DiscountId As Integer
<Key>
Public Property DiscountId() As Integer
Get
Return _DiscountId
End Get
Set(ByVal value As Integer)
If Not _DiscountId.Equals(value) Then
‘ Set the value
_DiscountId = value
End If
End Set
End Property
NOTE: If you ever have an issue whereby your WCF RIA Service is returning one row when you know you have many rows, chances are that the Key attribute is missing. Without this attribute, RIA views all rows as the same row and therefore only returns one.
Add a String Property for each Numeric Property
If you define a numeric property in your business object, such as an Integer or Decimal, and bind it in Silverlight, Silverlight will automatically convert any entered value to a number. If the user enters "one", it won’t generate a validation error. Silverlight instead converts it to a number. Any string converted to a number is 0.
This may not seem likely, but consider the possibility that the user enters 50%. Because of the "%" sign, Silverlight will convert the value to 0 and consider it a valid number.
To have full control over numeric entry, create a string version of any numeric property. Define a Regular Expression to validate that string as an integer or decimal value. And bind that string value to the Silverlight field.
In C#:
[RegularExpression("^([0-9]*\\,?[0-9]+|[0-9]+\\,?[0-9]*)?$",
errormessage = "Enter a dollar amount or percent value.")]
public string AmountString {
get { return Amount.ToString("N2"); }
set { decimal.TryParse(value, Amount); }
}
In VB:
<RegularExpression("^([0-9]*\,?[0-9]+|[0-9]+\,?[0-9]*)?$", errormessage:="Enter a dollar amount or percent value.")>
Public Property AmountString() As String
Get
Return Amount.ToString("N2")
End Get
Set(value As String)
Decimal.TryParse(value, Amount)
End Set
End Property
Add a Property for any Related Data
When updating data, RIA is much easier to work with if it manages related child data as a part of the parent data.
For example, say a discount is only applied to certain product types: downloadable software products allow one set of discounts, while sending CDs has a different set of available discounts. So a single discount has a set of products that it relates to.
To more easily edit this related data, create a property for the child data in the parent business object. Mark the relationship with the Association and Include attributes.
In C#:
[Include()]
[Association("Discount_Product", "DiscountId", "DiscountId")]
public List<Product> ProductList { get; set; }
In VB:
<Include>
<Association("Discount_Product", "DiscountId", "DiscountId")>
Public Property ProductList As List(Of Product)
Enjoy!