Validation on multiple WCF services with Single contract

Topics: Validation Application Block
Jul 24, 2012 at 8:41 AM

I've this scenario my architect has come up with. so far it has CRUD methods. but depending on what service we access, different entity is loaded into these services. therefore crud applies only to those particular entities.

 
public interface IServiceBase<TEntity> where TEntity : BusinessEntityBase<TEntity>, new()
    {
        [OperationContract]
        [FaultContract(typeof(ServiceFault))]
        int FetchCount(Specification<TEntity> predicate);

        [OperationContract]
        [FaultContract(typeof(ServiceFault))]
        IList<TEntity> FetchRange

        [OperationContract]
        [FaultContract(typeof(ValidationFault))]
        TEntity Add(TEntity entity);
    }

public class ExternalUserService : ServiceBase<ExternalUser>, IServiceBase<ExternalUser>, IDisposable
    {
               //notice here. there's in inherritance to base class and service contract. 
//assign repository here. (there's repository property exposed in FusionServiceBase)

}

Similary, another service say InternalUserService. these become 2 endpoints.
I'm trying to implement validation and exception handling block on these. (i've implemented these both on normal services which have 1:1 contract)
I foresee lot of problems here when I want to implement validation app block. firstly, 
all attributes go on 1 interface. this worries me as services may get more operation contracts in Future.
secondly, entlib config UI doesnt recognise any members as it's all in the base class.
this might not be right place to post but I couldn't post this on wcf forum either.
Please help. would this be the right approach? 
I tried something like this as well. but still unsure
public interface IExternaluserService : IServiceBase
    {
     
    }

 public class ExternalUserService : ServiceBase, IExternaluserService, IDisposable
    {

     }
Please help. Would this even be the right approach? ( I even had to change bit in beforeCall of ValidaitonParameterInspector.cs

 

Jul 25, 2012 at 6:53 AM

You are right, when dealing with generic interfaces and WCF the generic interface will have to be exposed with a concrete type so each TEntity you support will have to have a separate service.  Another approach is to use a base class with inheritance and using KnownType or ServiceKnownType.

For more flexibility you can avoid putting the validation attributes on the service interface but instead put them on the concrete objects that will be passed in.  E.g.:

    [DataContract]
    public class ExternalUser : BusinessEntityBase<ExternalUser>
    {
        [DataMember]
        [StringLengthValidator(2, 5)]
        public string Name
        {
            get;
            set;
        }
    }

Each TEntity/Service (in the posted model it's a 1:1 relationship) could have it's own rules.

If you are using configuration to store the validation rules then inheritance is not supported well (rules need to be duplicated from base class to derived class).

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 

Jul 25, 2012 at 9:57 AM

Thanks Randy. 

for flexibility reasons, I will keep the attributes on the concrete objects. 

but I wanted to keep them in configuration files. when you say duplicate, you mean copy paste the rules to concrete objects in config files? i thought this still wont work?

But I'll try before I speak more.

Thank you 

Jul 25, 2012 at 12:39 PM

I got it working by applying validators on ExternalUser directly.

but then not too happy as fault contract is still applied on IServiceBase.  Not sure if this gives me scope to scale for further needs.

If you've any further suggestion for applying validationFault contract, Please do let me know.

Many thanks

Kavya

Jul 26, 2012 at 5:43 AM

For information about validating inheritance trees via configuration see Why do validators that are configured in the base class not work in its subclasses? as well as the excellent blog entry Validator inheritance while using Validation Application Block configuration files.

You need to distinguish how data is validated with how that information is presented to the caller (or service consumer).  Using VAB with configuration is the internal method used to validate the data passed in to a service.  The users of the service don't particularly care about this.  However, how those results are presented to the user forms part of the service contract.  So, ValidationFault must be part of the service interface (contract) since it describes what data representation will be used to send back validation information.  ValidationFault is also quite usable/generic so other non-VAB information can also be presented via ValidationFaults (if you wish).

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com