Hi,
Ive implmented a simple rule in my BO when i attempted to save my BO it says that my object is invaild in the catch handler i understand the reason why its doing this, but how do i know which field in the BO is invaild ??
try
{
//Save Bo here....
}
Catch(Exception e)
{
// BO is invaild display which field is invaild
}
How did u guys implmented it ???
Thank you in advance.
Hi Reactance,
I recently subclassed BusinessBase. In there I made a public property that's a string of all the broken rules:
/// <summary> /// Gets the broken rules for this object. /// </summary> public virtual string BrokenRulesMessage{
get{
return BuildBrokenRulesMessage();}
}
/// <summary> /// Builds the broken rules message string. /// </summary> /// <returns></returns> private string BuildBrokenRulesMessage(){
StringBuilder sb = new StringBuilder(); foreach (BrokenRule rule in this.BrokenRulesCollection){
sb.Append(rule.Description);
sb.Append(
Environment.NewLine);}
return sb.ToString();}
Then when I try to save, you can do something like
catch (Csla.Validation.ValidationException){
string message = temp.BrokenRulesMessage; MessageBox.Show(message);}
I'm not that well versed with CSLA, just thought I'd throw out what I did.
Mike
Thank you for the speedy reply i`ll look in it tonight when i get home !
Is there anyone else with another way of doing this ?
:-)
This is already implemented in CSLA by using the following:
BO.BrokenRulesCollection.ToString
Michael,
I'm interested in what you had to do in order to subclass BusinessBase.
Did you subclass the other major classes also? BusinessListBase, ReadOnlyBase, etc.?
I'm trying to do that in order to add the broken rules collection as a public property plus the full rule list as a public property.
I started with BusinessBase and BusinessListBase subclasses.
All I wanted to do was the minimum necessary, so I defined the abstract classes and added one public BrokenRules property.
Then I went into ProjectTracker.Library and modified the Role and Roles classes to subclass my classes instead.
It's complaining that the Save method needs to return my subclass instead of Roles. I sure don't want to have to override every darn method in each one of the classes! Is there a simpler way?
David,
There was a thread 2 or 3 weeks ago where a bunch of code was posted showing examples of subclassing all the base classes - 6 in 2.0.3, and 7 in 2.1.
Anyway, here's an example of BusinessBase. I added in those two methods, take them out if you want the bare minimum.
namespace
Buoy.BusinessObjects20{
[
Serializable()] public abstract class BuoyBusinessBase<T> : BusinessBase<T> where T : BuoyBusinessBase<T>{
/// <summary> /// Marks the object as clean. Should be used when creating a new /// object and you don't want it saved unless the user actually /// changes something. /// </summary> public virtual void MarkAsClean(){
this.MarkClean();}
/// <summary> /// Gets the broken rules for this object. /// </summary> public virtual string BrokenRulesMessage{
get{
return this.BrokenRulesCollection.ToString();}
}
}
}
Not sure what's happening with that save business.
Regards,
Mike
Edit: Yes, I subclassed all of those classes. That way you're set up to make your modifications, if need be. It's the recommended approach.
BusinessBase seemed to work ok for me.
But BusinessListBase is where I had the problem.
Here's my BusinessListBase
namespace
Buoy.BusinessObjects20{
[
Serializable] public abstract class BuoyBusinessListBase<T, C> : BusinessListBase<T, C> where T : BuoyBusinessListBase<T, C> where C : Csla.Core.IEditableBusinessObject{
}
}
Found the other thread on subclassing...
Ok, I've had a partial success on subclassing the main csla classes and publically exposing the broken rules collection.
I'm using Role, Roles, and EditRoles from PTWeb for my test case, in order to determine what changes to the "standard" way of coding things need to be done.
With the concept that a rule can be in a warning state, it's possible for an object that has just been loaded will have broken rules. (Ditto if we just changed the rules in the object but didn't update the data in the database, but that's another topic. :)
So, I added ValidationRules.CheckRules() to the end of the private constructor in Role so that the object would check its rule status upon being created. I also added a max string length of 10 rule to the Name property so some of the existing Roles would be considered broken.
It blew up. (Details of error at end of message.)
I changed it to ValidationRules.CheckRules("Name") and it worked perfectly.
Turns out the problem is being caused by the NoDuplicates instance rule on the Id property.
Ok, so maybe it's in a state of flux being halfway thru the constructor of a just added (or about to be added) Role. Option 2 was to loop thru each Role in the Roles collection and ask it to check its rules. Not ideal, but hey. Can't do it though, the ValidationRules.CheckRules() is private.
I may be able to override the CheckRules and make it accessible to its parent, or just fake it with another method to do just that, but frankly, it seems that the real problem is with CheckRules() or the implementation of the NoDuplicates rule. It should just work. :(
If you have ideas, feel free to pass them on. I'll keep working on it.
Here's the error I get:
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.
Source Error:
Line 99: {
Line 100: Roles parent = (Roles)this.Parent;
Line 101: foreach (Role item in parent)
Line 102: if (item.Id == _id && !ReferenceEquals(item, this))
Line 103: {
Source File: C:\Visual Studio Projects\ProjectTracker20cs\ProjectTracker.Library\Admin\Role.cs Line: 101
Stack Trace:
[NullReferenceException: Object reference not set to an instance of an object.]
ProjectTracker.Library.Admin.Role.NoDuplicates(Object target, RuleArgs e) in C:\Visual Studio Projects\ProjectTracker20cs\ProjectTracker.Library\Admin\Role.cs:101
Csla.Validation.RuleMethod.Invoke(Object target) in C:\Visual Studio Projects\Csla20cs\Csla\Validation\RuleMethod.cs:96
Csla.Validation.ValidationRules.CheckRules(List`1 list) in C:\Visual Studio Projects\Csla20cs\Csla\Validation\ValidationRules.cs:658
Csla.Validation.ValidationRules.CheckRules() in C:\Visual Studio Projects\Csla20cs\Csla\Validation\ValidationRules.cs:630
ProjectTracker.Library.Admin.Role..ctor(SafeDataReader dr) in C:\Visual Studio Projects\ProjectTracker20cs\ProjectTracker.Library\Admin\Role.cs:154
ProjectTracker.Library.Admin.Role.GetRole(SafeDataReader dr) in C:\Visual Studio Projects\ProjectTracker20cs\ProjectTracker.Library\Admin\Role.cs:134
ProjectTracker.Library.Admin.Roles.DataPortal_Fetch(Criteria criteria) in C:\Visual Studio Projects\ProjectTracker20cs\ProjectTracker.Library\Admin\Roles.cs:144
[CallMethodException: DataPortal_Fetch method call failed]
Csla.MethodCaller.CallMethod(Object obj, MethodInfo info, Object[] parameters) in C:\Visual Studio Projects\Csla20cs\Csla\DataPortal\MethodCaller.cs:118
Csla.Server.SimpleDataPortal.Fetch(Type objectType, Object criteria, DataPortalContext context) in C:\Visual Studio Projects\Csla20cs\Csla\DataPortal\Server\SimpleDataPortal.cs:109
[DataPortalException: DataPortal.Fetch failed (System.NullReferenceException: Object reference not set to an instance of an object.
at ProjectTracker.Library.Admin.Role.NoDuplicates(Object target, RuleArgs e) in C:\Visual Studio Projects\ProjectTracker20cs\ProjectTracker.Library\Admin\Role.cs:line 101
at Csla.Validation.RuleMethod.Invoke(Object target) in C:\Visual Studio Projects\Csla20cs\Csla\Validation\RuleMethod.cs:line 96
at Csla.Validation.ValidationRules.CheckRules(List`1 list) in C:\Visual Studio Projects\Csla20cs\Csla\Validation\ValidationRules.cs:line 658
at Csla.Validation.ValidationRules.CheckRules() in C:\Visual Studio Projects\Csla20cs\Csla\Validation\ValidationRules.cs:line 630
at ProjectTracker.Library.Admin.Role..ctor(SafeDataReader dr) in C:\Visual Studio Projects\ProjectTracker20cs\ProjectTracker.Library\Admin\Role.cs:line 154
at ProjectTracker.Library.Admin.Role.GetRole(SafeDataReader dr) in C:\Visual Studio Projects\ProjectTracker20cs\ProjectTracker.Library\Admin\Role.cs:line 134
at ProjectTracker.Library.Admin.Roles.DataPortal_Fetch(Criteria criteria) in C:\Visual Studio Projects\ProjectTracker20cs\ProjectTracker.Library\Admin\Roles.cs:line 144)]
Csla.DataPortal.Fetch(Type objectType, Object criteria) in C:\Visual Studio Projects\Csla20cs\Csla\DataPortal\Client\DataPortal.cs:192
Csla.DataPortal.Fetch(Object criteria) in C:\Visual Studio Projects\Csla20cs\Csla\DataPortal\Client\DataPortal.cs:140
ProjectTracker.Library.Admin.Roles.GetRoles() in C:\Visual Studio Projects\ProjectTracker20cs\ProjectTracker.Library\Admin\Roles.cs:86
RolesEdit.GetRoles() in c:\Visual Studio Projects\ProjectTracker20cs\www\PTWeb\RolesEdit.aspx.cs:68
RolesEdit.RolesDataSource_SelectObject(Object sender, SelectObjectArgs e) in c:\Visual Studio Projects\ProjectTracker20cs\www\PTWeb\RolesEdit.aspx.cs:126
Csla.Web.CslaDataSource.OnSelectObject(SelectObjectArgs e) in C:\Visual Studio Projects\Csla20cs\Csla\Web\CslaDataSource.cs:150
Csla.Web.CslaDataSourceView.ExecuteSelect(DataSourceSelectArguments arguments) in C:\Visual Studio Projects\Csla20cs\Csla\Web\CslaDataSourceView.cs:94
System.Web.UI.DataSourceView.Select(DataSourceSelectArguments arguments, DataSourceViewSelectCallback callback) +17
System.Web.UI.WebControls.DataBoundControl.PerformSelect() +149
System.Web.UI.WebControls.BaseDataBoundControl.DataBind() +70
System.Web.UI.WebControls.GridView.DataBind() +4
System.Web.UI.WebControls.BaseDataBoundControl.EnsureDataBound() +82
System.Web.UI.WebControls.CompositeDataBoundControl.CreateChildControls() +69
System.Web.UI.Control.EnsureChildControls() +87
System.Web.UI.Control.PreRenderRecursiveInternal() +41
System.Web.UI.Control.PreRenderRecursiveInternal() +161
System.Web.UI.Control.PreRenderRecursiveInternal() +161
System.Web.UI.Control.PreRenderRecursiveInternal() +161
System.Web.UI.Control.PreRenderRecursiveInternal() +161
System.Web.UI.Control.PreRenderRecursiveInternal() +161
System.Web.UI.Control.PreRenderRecursiveInternal() +161
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1360
I re-wrote the NoDuplicates rule as follows:
private bool NoDuplicates(object target, Csla.Validation.RuleArgs e)Basically, the original rule assumed that this.Parent would return something. I added a check to make sure that it did before I tried to verify that there were no duplicates.
Copyright (c) Marimer LLC