Very basic insert routine, but this object is used for my edit routine and has a child object. When I try to do an insert, it is telling me that my validation is required for my child object. Why?
Here is my child object.
public readonly static PropertyInfo<HighlightEdit> HighlightProperty = RegisterProperty<HighlightEdit>(p => p.Highlight);
public HighlightEdit Highlight
{
get
{
if (!(FieldManager.FieldExists(HighlightProperty)))
LoadProperty(HighlightProperty, DataPortal.CreateChild<HighlightEdit>());
return GetProperty(HighlightProperty);
}
private set { LoadProperty(HighlightProperty, value); }
}
My validation logic is as follows:
protected override void AddBusinessRules()
{
// TODO: add validation rules
//BusinessRules.AddRule(new Rule(), IdProperty);
base.AddBusinessRules();
BusinessRules.AddRule(new StartDateGTEndDate { PrimaryProperty = StartDateProperty, AffectedProperties = { StartDateProperty, EndDateProperty, HighlightTitleProperty, DisplayOrderProperty, FK_Digital_Asset_GuidProperty } });
BusinessRules.AddRule(new StartDateGTEndDate { PrimaryProperty = EndDateProperty, AffectedProperties = { EndDateProperty, StartDateProperty, HighlightTitleProperty, DisplayOrderProperty, FK_Digital_Asset_GuidProperty } });
BusinessRules.AddRule(new TitleRequiredIfDirty { PrimaryProperty = HighlightTitleProperty, AffectedProperties = { HighlightTitleProperty, StartDateProperty, EndDateProperty, DisplayOrderProperty, FK_Digital_Asset_GuidProperty } });
BusinessRules.AddRule(new DisplayOrderRequired { PrimaryProperty = DisplayOrderProperty, AffectedProperties = { DisplayOrderProperty, StartDateProperty, EndDateProperty, HighlightTitleProperty, FK_Digital_Asset_GuidProperty } });
BusinessRules.AddRule(new ImageRequired { PrimaryProperty = FK_Digital_Asset_GuidProperty, AffectedProperties = { FK_Digital_Asset_GuidProperty, StartDateProperty, EndDateProperty, HighlightTitleProperty, DisplayOrderProperty } });
BusinessRules.AddRule(new StartDateRequired { PrimaryProperty = StartDateProperty, AffectedProperties = { StartDateProperty, EndDateProperty, HighlightTitleProperty, DisplayOrderProperty, FK_Digital_Asset_GuidProperty } });
BusinessRules.AddRule(new EndDateRequired { PrimaryProperty = EndDateProperty, AffectedProperties = { StartDateProperty, EndDateProperty, HighlightTitleProperty, DisplayOrderProperty, FK_Digital_Asset_GuidProperty } });
}
private class StartDateGTEndDate : Csla.Rules.BusinessRule
{
protected override void Execute(Csla.Rules.RuleContext context)
{
var target = (HighlightEdit)context.Target;
var started = target.ReadProperty(StartDateProperty);
var ended = target.ReadProperty(EndDateProperty);
if (started.HasValue && ended.HasValue && started > ended || !started.HasValue && ended.HasValue)
context.AddErrorResult("Start date can't be after end date");
}
}
private class TitleRequiredIfDirty : Csla.Rules.BusinessRule
{
protected override void Execute(Csla.Rules.RuleContext context)
{
var target = (HighlightEdit)context.Target;
var title = target.ReadProperty(HighlightTitleProperty);
if (title.Length <= 0)
context.AddErrorResult("Title required.");
}
}
private class DisplayOrderRequired : Csla.Rules.BusinessRule
{
protected override void Execute(Csla.Rules.RuleContext context)
{
var target = (HighlightEdit)context.Target;
var displayOrder = target.ReadProperty(DisplayOrderProperty);
if (!displayOrder.HasValue)
context.AddErrorResult("Display order required.");
}
}
private class EndDateRequired : Csla.Rules.BusinessRule
{
protected override void Execute(Csla.Rules.RuleContext context)
{
var target = (HighlightEdit)context.Target;
var endDate = target.ReadProperty(EndDateProperty);
if (!endDate.HasValue)
context.AddErrorResult("End date required.");
}
}
private class StartDateRequired : Csla.Rules.BusinessRule
{
protected override void Execute(Csla.Rules.RuleContext context)
{
var target = (HighlightEdit)context.Target;
var startDate = target.ReadProperty(StartDateProperty);
if (!startDate.HasValue)
context.AddErrorResult("Start date required.");
}
}
private class ImageRequired : Csla.Rules.BusinessRule
{
protected override void Execute(Csla.Rules.RuleContext context)
{
var target = (HighlightEdit)context.Target;
var guid = target.ReadProperty(FK_Digital_Asset_GuidProperty);
if (!guid.HasValue)
{
if (target.ReadProperty(FK_Digital_Asset_IdProperty) != null)
{
return;
}
else
{
context.AddErrorResult("Image required.");
}
}
}
}
If I remove said validation, the object is inserted correctly. Why is my validation firing off when none of the properties were chagned?
My modelstate shows the errors, but I am confused as to why it is trying to validate an object that I have not modified.
If I change my LoadProperty to a fetchChild instead of Create child, my object is not dirty but is this the correct way to fix my parent objects child object?
public readonly static PropertyInfo<SF.Library.HighlightAssignment.HighlightAssignmentEdit> HighlightProperty = RegisterProperty<SF.Library.HighlightAssignment.HighlightAssignmentEdit>(p => p.Highlight);
public SF.Library.HighlightAssignment.HighlightAssignmentEdit Highlight
{
get
{
if (!(FieldManager.FieldExists(HighlightProperty)))
// LoadProperty(HighlightProperty, DataPortal.CreateChild<HighlightAssignmentEdit>());
LoadProperty(HighlightProperty, DataPortal.FetchChild<HighlightAssignmentEdit>(null));
return GetProperty(HighlightProperty);
}
private set { LoadProperty(HighlightProperty, value); }
}
The reason your validation rules are running on creation is because the base implementation of Child_Create() runs ValidationRules.CheckRules() whereas a Child_Fetch() does not unless specifically added by your code.
Given that these fields are required, it is probably a good thing the validation rules are running but that all depends on your use case, you may want to create a new child object if the root is new and fetch on an existing root object.If that was the case I would call the CreateChild in your DataPortal_Create method on your root object and leave the lazy loaded code to only do a fetch (because you would assume if it hadn't be loaded then you had fetched the object).
The only thing to be careful of, is that the Create/FetchChild methods do not go across to the AppServer like a standard DataPortal.Create/Fetch which depending on how you deploy may be an issue for you.
Copyright (c) Marimer LLC