WCF Validation - MessageContract with DataContract

Topics: Validation Application Block
Jul 30, 2007 at 5:52 PM
I'm having a problem with WCF Integration with the Validation Block. When I have a DataContract nested in a MessageContract, the validation is not occurring on the DataContract fields. Only validators on the MesasgeContract level are working. If I use the DataContract by itself as the input message, then the the validators do work.

I'm currently running EntLib 3.0. Any ideas? Thanks!
Jul 30, 2007 at 6:43 PM
Hi David,

Validations are applied to the .NET objects, regarless of their role in WCF, and this validation doesn't navigate the properties unless explicitly indicated. You will need to use the ObjectValidator to the fields or properties that have a DataContract type in your message contract class.

Regards,
Fernando
Jul 30, 2007 at 7:25 PM
Hmmm. Let me elaborate - I'm using the [ValidationBehavior] and [FaultContract(typeof(ValidationFault))] attributes in Microsoft.Practices.EnterpriseLibrary.Validation.Integration.WCF. They should take care of this without extra code, right?

I get the desired behavior (a ValidationFault is sent to the client) when the validators are on the MessageContract, but not the nested DataContract. Is the WCF integration not smart enough to validate child DataContracts?

Using the example code below, if I call DoStuff() with DataContracts.RequestData.String1not equal to "One" or "Two" then a ValidationFault is sent to the client. However, calling DoStuffNew() with the same data in the DataContract nested inside the ServiceContracts.RequestMessage, then no fault is generated.

If I call DoStuffNew() with ServiceContracts.RequestMessage.Data = null, then I get the NotNull ValidationFault. It seems to be only validating the top level object.


namespace WCFService1.ServiceContracts
{
[ServiceContract(Namespace = "http://WCFService1.ServiceContracts/2007/05", Name = "ITestService", SessionMode = SessionMode.Allowed)]
[ValidationBehavior]
public interface ITestService
{
[OperationContract(IsTerminating = false, IsInitiating = true, IsOneWay = false, AsyncPattern = false, Action = "DoStuff")]
[FaultContract(typeof(ValidationFault))]
WCFService1.DataContracts.ResponseData DoStuff(WCFService1.DataContracts.RequestData request);

[OperationContract(IsTerminating = false, IsInitiating = true, IsOneWay = false, AsyncPattern = false, Action = "DoStuffNew")]
[FaultContract(typeof(ValidationFault))]
WCFService1.ServiceContracts.ResponseMessage DoStuffNew(WCFService1.ServiceContracts.RequestMessage request);

}


namespace WCFService1.ServiceContracts
{
[MessageContract]
public class RequestMessage
{
private System.String UserIDField;

[MessageHeader()]
public System.String UserID
{
get { return UserIDField; }
set { UserIDField = value; }
}

private WCFService1.DataContracts.RequestData DataField;

[MessageBodyMember(Order = 1)]
[NotNullValidator()]
public WCFService1.DataContracts.RequestData Data
{
get { return DataField; }
set { DataField = value; }
}

}
}

namespace WCFService1.DataContracts
{
[DataContract(Namespace = "http://WCFService1.DataContracts/2007/05", Name = "RequestData")]
public partial class RequestData
{
private System.String String1Field;

[DataMember(IsRequired = false, Name = "String1", Order = 0)]
[DomainValidator("One", "Two")]
public System.String String1
{
get { return String1Field; }
set { String1Field = value; }
}

}
}

Jul 30, 2007 at 7:32 PM
OK, Disregard that last post. I used the ObjectValidator like you said and it works fine.

Thanks for your help Fernando!