I Solved my problem by doing the following:
Setup int the WCF Integration:
(Microsoft.Practices.EnterpriseLibrary.Validation.Integration.WCF)
Create a simple marker Attribute:
public class ValidationKeyAttribute : Attribute
{
}
which will be put on the Property that identifies the data record.
Create an Interface:
public interface IValidationBackReference
{
object BackReference { get; set; }
}
This is for the reference from the City record to the Country record in the above example so that all Identifiers up the chain also get included
Modify the BeforeCall()
Method in ValidationParameterInspector
to crawl all inputs and set the BackReference
using something like this:
private void SearchForBackReferences(object input, object backReference)
{
if (input == null)
{
return;
}
Type t = input.GetType();
if (t.IsArray)
{
Object[] inputs = (object[])input;
SearchForBackReferences(inputs, backReference);
}
else if (input is IValidationBackReference)
{
foreach (PropertyInfo info in t.GetProperties())
{
object value = info.GetValue(input, null);
SearchForBackReferences(value, input);
}
((IValidationBackReference)input).BackReference = backReference;
}
}
private void SearchForBackReferences(object[] inputs, object backReference)
{
if(inputs==null)
{
return;
}
foreach (object input in inputs)
{
SearchForBackReferences(input, backReference);
}
}
Modify the CreateValidationDetail
method in ValidationParameterInspector
to go up the record tree via the BackReferences with something like this
private static string FindKey(object target)
{
StringBuilder result = new StringBuilder();
if( target == null )
{
return result.ToString();
}
if(target is IValidationBackReference)
{
result.Append(FindKey(((IValidationBackReference) target).BackReference));
}
Type t = target.GetType();
foreach (var info in t.GetProperties())
{
if (Attribute.IsDefined(info, typeof(ValidationKeyAttribute)))
{
object objectValue = info.GetValue(target, null);
string stringValue = "(null)";
if (objectValue != null)
{
stringValue = objectValue.ToString();
}
result.Append(string.Format("{0} = '{1}'; ",info.Name, stringValue));
}
}
return result.ToString();
}
and put it into the Details.Key
of the ValidationKDetail
. So far the Setup.
In the Webservice
all you have to do now is Implement the IValidationBackReference
interface on the classes used by the Webservice and put the [ValidationKey]
Attribute on appropriate Properties.
The example above would look like:
public class Continent : IValidationBackReference
{
public object BackReference { get; set; }
[ValidationKey]
public string Name { get; set; }
public Country[] Countries{ get; set; }
}
public class Country : IValidationBackReference
{
public object BackReference { get; set; }
[ValidationKey]
public string Name { get; set; }
public City[] Cities { get; set; }
}
public class City : IValidationBackReference
{
public object BackReference { get; set; }
[ValidationKey]
public string Mayor { get; set; }
}
what a monster ...