Architecting Silverlight LOB applications (Part 4) – Metadata and localization

Specifying metadata for our entities is the easy part and here is a good place to start localizing our app.

First what we have to do is create a buddy class as described in the following example:

public partial class Customer
    internal class CustomerMetadata
        [Display(ResourceType = typeof(Metadata), Name = "MyApp_Customer_Number")]
        public int Number;

        [Display(ResourceType = typeof(Metadata), Name = "CommonProperties_Email")]
        public string Email;

        public EntityCollection<Order> Orders;
public partial class Employee
    internal class EmployeeMetadata
        [Display(ResourceType = typeof(Metadata), Name = "CommonProperties_Name")]
        [StringLength(128, ErrorMessageResourceType = typeof(Metadata), ErrorMessageResourceName = "CommonErrors_StringLength")]
        public string Name;

        [Display(ResourceType = typeof(Metadata), Name = "CommonProperties_Email")]
        public string Email;

        public Department Department;

The DisplayAttribute attribute is very useful, as it annotates your properties with information that can be consumed in various ways. For example, when using your entity in a Datagrid, the cell headers will automatically look up for DisplayAttributes and retrieve the localized string for that property. The same applies for labels in a Dataform and if you want to create your own UI framework, you can leverage this type of annotation to start localizing your app. Notice how I’ve reused some resource names for common properties like Email. The same could have been done for Number and Name, but that really depends on each case.

You can place validation rules on your properties as well using attributes like StringLength, apply regular expressions or even create your own custom validation rules. The great part about this is that those rules will be available in the client as well. The DomainService makes sure that before executing operations on entities all the validation rules are applied. Note that you can’t do all kinds of validation on your entities using metadata. Some validations may require connecting to a database, transactions, etc, and such information isn’t available in this type of validation context. I recommend that such validations are performed after DomainService’s ExecuteChangeSet is invoked and right before the PersistChangeSet method.

More on metadata specification can be found in the documentation or other resources on the web. I just want to focus on a different aspect that not many people tend to write about. That is sharing the Resources in the client and the server. The client project will not compile if the ResourceManager Metadata isn’t available. Since it is defined on the server, you should follow these steps in order to enable it on the client:

  • Add the resource files as a link to the client project
  • Change your client project’s default namespace to the same namespace that is defined in the server project that holds the resource files
  • Change the client project’s .csproj where it references the linked Designer.cs file and add these lines of code:

      <Compile Include=”..\..\..\Server\Data\MyApp.Data\Resources\Metadata.Designer.cs”>

            <AutoGen>True</AutoGen>      <Link>Resources\Metadata.Designer.cs</Link>




  • Make sure the resource files have the same relative path in the client project as in the server project. In this case, I’ve created a Resources folder in both projects.
  • Also make sure that the resource file has Public marked as its Access Modifier.

These steps are necessary because adding linked files for dependent files, like Medatata.resx / Metadata.Designer.cs won’t automatically mark them as dependent, so you need to do it manually.

Now you should be able to compile your application and start taking advantage of metadata in your entities.

To finish, I’d like to say that all the code is available at under trunk/2010/SL-MVVM-RIA. I’m sorry for the delay on this one.

Next posts will be covering client development.


C# Tips: IEnumerable<T>.ForEach extension method

I’m sure everyone have already used IEnumerable<T> extension methods to query your .NET collections.

Well, one thing we usually do is loop through a collection’s items and do something.

Lets say I want to write some data about portuguese people I find in my persons collection and then retrieve the maximum age value to do something else:

void Work()
    var persons = RetrievePersons();

    var portuguesePeople = persons.Where(p => p.Country == "Portugal");
    int maxAge;
    foreach (var p in persons.Where(p => p.Country == "Portugal"))
        Console.WriteLine("Name: {0} ; Age: {1}", p.Name, p.Age);

    maxAge = portuguesePeople.Max(p => p.Age);

Because the foreach statement can’t be used in a fluent API (eg. Linq) we need an extra reference so the portuguese results we’re looping through can be reused when retrieving the max age value. Being able to write code in a fluent API makes it easier to read and reduces the number of (sometimes unnecessary) variables in your code.

C# has a ForEach instance method for List<T> but most of the times you will be dealing with IEnumerable<T> references, so a ForEach extension method would be handy in these cases.

Continue reading