Share EntLib Validator Attributes between Client and Server with RIA Services

Topics: Silverlight Integration Pack, Validation Application Block
Dec 13, 2012 at 8:22 PM
Doesn't support EntLib Validation Application Block 5.0 (Update 1) sharing validation attributes between server and client with Silverlight/RIA Services? If i switch my Visual Studio project back to Silverlight 4 all attributes are available on client side. With SL5 it works only with DataAnnotations, but there are no EntLib attributes in the generated code. Kind regards Christian
Dec 14, 2012 at 8:10 AM
Edited Dec 14, 2012 at 3:30 PM

Yes, I can confirm this is a problem.  

The issue is that the Validation Application Block for Silverlight references System.ComponentModel.DataAnnotations version  However Silverlight 5 references the newer System.ComponentModel.DataAnnotations version  Silverlight handles this fine at runtime, however the RIA Services code generator is not happy with this scenario.  If you enable diagnostic output from MSBuild (Tools->Options->Projects and Solutions->Build and Run) and rebuild you will see the error:

 Failed to load types from assembly 'Microsoft.Practices.EnterpriseLibrary.Validation.Silverlight, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' so the assembly will be ignored.
  Cannot resolve dependency to assembly 'System.ComponentModel.DataAnnotations, Version=, Culture=neutral, PublicKeyToken=ddd0da4d3e678217' because it has not been preloaded. When using the ReflectionOnly APIs, dependent assemblies must be pre-loaded or loaded on demand through the ReflectionOnlyAssemblyResolve event. (TaskId:96)

Usually for these types of scenarios you would implement a binding redirect or custom assembly resolving.  The good news is that the error message points us in the right direction which seems similar to the typical approach.  The bad news is that this is a code generator running during the build so a binding redirect does not help. 

Luckily, the RIA team has placed some hooks to help us out.  What we can do is add a custom code generator to resolve the assembly.  

First, I went to Nuget and installed in the web (server side) project RIAServices.T4 and then also added a reference to System.ComponentModel.Composition.  

Next I created an EntlibValidationCodeGenerator class to resolve the old assembly:

using System;
using System.IO;
using System.Reflection;
using Microsoft.ServiceModel.DomainServices.Tools;
using Microsoft.ServiceModel.DomainServices.Tools.TextTemplate.CSharpGenerators;

namespace ValidationRia.Web
    [DomainServiceClientCodeGeneratorAttribute("EntlibValidationCodeGenerator", "C#")]
    public class EntlibValidationCodeGenerator : CSharpClientCodeGenerator
        static EntlibValidationCodeGenerator()
            AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += new ResolveEventHandler(CurrentDomain_ReflectionOnlyAssemblyResolve);

        private static Assembly CurrentDomain_ReflectionOnlyAssemblyResolve(object sender, ResolveEventArgs args)
                return System.Reflection.Assembly.ReflectionOnlyLoad(args.Name);
            catch (FileNotFoundException e)
                if (args.Name.StartsWith("System.ComponentModel.DataAnnotations, Version="))
                    // Put this assembly in a reasonable common folder, e.g. Lib, etc. so that you can build on all machines
                    byte[] readAllBytes = File.ReadAllBytes(@"C:\Program Files (x86)\Microsoft SDKs\Silverlight\v4.0\Libraries\Client\System.ComponentModel.DataAnnotations.dll");
                    return System.Reflection.Assembly.ReflectionOnlyLoad(readAllBytes);

            return null;

After that, a recompile should show the Enterprise Library Validators applied to the Generated_Code.

Randy Levy
Enterprise Library support engineer
Support How-to 

Dec 21, 2012 at 7:58 AM

Thanks a lot, it works :-)

Kind regards