Hi
Something simple which I cannot get to work :-)
I need a rule that will examine two properties and error if both are blank. I have created this rule so it takes two IPropertInfo objects.
public class EitherHaveValue : CommonBusinessRule
{
IPropertyInfo SecondaryProperty {get; set;}
/// <summary>
/// Creates an instance of the rule.
/// </summary>
/// <param name="primaryProperty">Property to which the rule applies.</param>
public EitherHaveValue(IPropertyInfo primaryProperty, IPropertyInfo secondaryProperty)
: base(primaryProperty)
{
PrimaryProperty = primaryProperty;
SecondaryProperty = secondaryProperty;
//this.AffectedProperties.Add(PrimaryProperty);
this.AffectedProperties.Add(SecondaryProperty);
InputProperties = new List<IPropertyInfo> { primaryProperty, secondaryProperty };
}
/// <summary>
/// Rule implementation.
/// </summary>
/// <param name="context">Rule context.</param>
protected override void Execute(RuleContext context)
{
var value = context.InputPropertyValues[PrimaryProperty];
var value2 = context.InputPropertyValues[SecondaryProperty];
#if WINDOWS_PHONE
if (value == null || string.IsNullOrEmpty(value.ToString()))
#else
if (value == null || string.IsNullOrWhiteSpace(value.ToString()))
#endif
{
#if WINDOWS_PHONE
if (value2 == null || string.IsNullOrEmpty(value2.ToString()))
#else
if (value2 == null || string.IsNullOrWhiteSpace(value2.ToString()))
#endif
{
var message =
string.Format(PrimaryProperty.FriendlyName + " or " + SecondaryProperty.FriendlyName +
" required.");
context.Results.Add(new RuleResult(RuleName, PrimaryProperty, message) {Severity = Severity});
//context.Results.Add(new RuleResult(RuleName, SecondaryProperty, message) {Severity = Severity});
}
}
}
}
I can only get this to work properly by adding it twice to the BusinssRules property in the BO:
BusinessRules.AddRule(new Csla.Extensions.Rules.EitherHaveValue(TypeProperty, ValueProperty));
BusinessRules.AddRule(new Csla.Extensions.Rules.EitherHaveValue(ValueProperty, TypeProperty));Doing this however gives me two errors instead of one?I'm obviously doing this wrong, any ideas?RegardsKevin Fairclough
Hi,
Here is the AnyRequired rule from CslaContrib:
Remember to add a Dependency rule from field2 to field1 to make the rule run also when field2 is changed.
BusinessRules.AddRule(new AnyRequired(TypeProperty, ValueProperty, Value2Property)); BusinessRules.AddRule(new Dependency(ValueProperty, TypeProperty));
The AnyRequired rule:
/// <summary> /// Check that at least one of the fields of type string or smartvalue field has a value. /// Code must also add Dependency rules from each additional properties to primary property. /// </summary> public class AnyRequired : CommonBusinessRule { /// <summary> /// Initializes a new instance of the <see cref="AnyRequired"/> class. /// </summary> /// <param name="primaryProperty">The primary property.</param> /// <param name="additionalProperties">The additional properties.</param> public AnyRequired(IPropertyInfo primaryProperty, params IPropertyInfo[] additionalProperties) : base(primaryProperty) { if (InputProperties == null) InputProperties = new List<IPropertyInfo>(); InputProperties.AddRange(additionalProperties); } /// <summary> /// Initializes a new instance of the <see cref="AnyRequired"/> class. /// </summary> /// <param name="primaryProperty">The primary property.</param> /// <param name="errorMessageDelegate">The error message function.</param> /// <param name="additionalProperties">The additional properties.</param> public AnyRequired(IPropertyInfo primaryProperty, Func<string> errorMessageDelegate, params IPropertyInfo[] additionalProperties) : this(primaryProperty, additionalProperties) { ErrorMessageDelegate = errorMessageDelegate; } /// <summary> /// Gets the error message. /// </summary> /// <value></value> protected override string ErrorMessage { get { return HasErrorMessageDelegate ? base.ErrorMessage : CslaContrib.Properties.Resources.AnyRequiredRule; } } /// <summary> /// Executes the rule in specified context. /// </summary> /// <param name="context">The context.</param> protected override void Execute(RuleContext context) { foreach (var field in context.InputPropertyValues) { // smartfields have their own implementation of IsEmpty var smartField = field.Value as ISmartField; if (smartField != null) { if (!smartField.IsEmpty) return; } else if (field.Value != null && !field.Value.Equals(field.Key.DefaultValue)) return; } var fields = context.InputPropertyValues.Select(p => p.Key.FriendlyName).ToArray(); var fieldNames = String.Join(", ", fields); context.AddErrorResult(string.Format(ErrorMessage, fieldNames)); } }
Thanks Jonny
This works however the dependant property doesn't get an error adorner in our WPF, only the primary property.
Thanks
Kevin
Hi,
There's been a lot of discussions here on whether to set error/warnin etc on other fields.
Truth is - this has not worked as expected up until now and has been fixed i Csla 4.2 (trunk only) so that f.ex an AnyRequired rule can
So when you move to Csla 4.2 this will be possible within just one rule.
Copyright (c) Marimer LLC