I have a read only object that need to call AddBusinessRules to do some data validations for the user inputs used in search, but I'm getting "ValidationRules.AddRule is not accessible in this context" error as it is protected. I understand why I'm getting this error is because the Object that calls the "ValidationRule.AddRule" is a Read Only Object, but ValidationRule is defined in BusinessBase.
So is it possible for RO object to use VlidationRule to do any data entry validation then?
Any insights is appreciated.
A read-only object can only have read-only properties (or at least that's all that CSLA supports), so there's never a reason to have validation rules in a read-only object.
If you want to have input fields on your search form, you should bind them to an editable root object - though perhaps one that doesn't actually do any data access. Your read-only list can have a factory that accepts the input object (editable root) as a parameter:
Private Shared Function GetList(userInput As SearchInput)
' ...
End Function
The SearchInput class would be an editable root, but with none of the data access code. In other words, it would have only properties and business rules.
Okay I see. Thanks Rocky for pointing me at a different direction I never thought of before.
I thought my app only needed read-only and read-only list because it basically emcompasses several search input forms/controls and a list of search results for each search form/control. Each search result is read-only list, which has a criteria class defined. Each search form/control is binded to the criteria class (I use it as search criteria).
To clarify, I already have a factory in read-only list that accepts criteria class as a parameter, so what I'm getting at from your solution is that I will need to create an editable root object to replace the criteria class I'm using now to have the search form bind to. That will allow the search form to have validation rules such as data validation etc. In this case, criteria class will not be needed any more, right?
My second question on this, would it make difference if I change the criteria to inherit from BusinessBase instead of being created within a read-only list (I'm sure it will)? I guess my question is what is the difference to create an editable root object vs. use criteria as an editable root object?
Thank you very much for your time and helps.
I have a lot of search screens in my app and I created Root BOs with validation rules in them just as Rocky describes. Then when the user clicks Search, the valid BO is passed to the ROC as a parameter and is used to determine which records to fetch.
There are no DataPortal methods - the factory just uses a New constructor to build an instance of the BO.
e.g.
<Serializable()> _
Joe
If you don't call the data portal, then you must be doing the data access directly? You'll never be able to use a remote data portal in that case.
What I recommend is passing the valid BO into the ROC factory method as a parameter. In the factory method you should call the data portal, passing a criteria object, and the data load should occur in the ROC's DataPortal_Fetch().
There are a couple ways you can create the criteria object:
Overall I think I'd lean toward that last option: separate BO (with no data access of its own) that is then passed into the Criteria object's constructor and exposed as a property of the Criteria for use in your DP_Fetch() method.
Thank you both Joe and Rocky for sharing your thoughts and solutions.
In my case (as stated in my previous post), my app is definitely missing an editable root object that allows putting in validation rules. And I will continue to use the data portal to do data access.
I have a few questions for the three options of creating the criteria object Rocky provided:
Overall I think I'd lean toward that last option: separate BO (with no data access of its own) that is then passed into the Criteria object's constructor and exposed as a property of the Criteria for use in your DP_Fetch() method. >>> I want to try this solution.
Is the following prototype heading the right direction? Thanks for your time and help!
Public
Class SearchInputInherits BusinessBase(of SearchInput)
End Class
Public
Class SearchResultListInherits ReadOnlyListBase(Of SearchResultList, SearchResultInfo)
Public Shared Function GetSearchResultList(ByVal UserInput As SearchInput) As SearchResultList
Return DataPortal.Fetch(Of SearchResultList)(New FilteredCriteria(UserInput))
End Function
Private Sub New()
' require use of factory methods
End Sub
<Serializable()> _
Private Class FilteredCriteria
Private mUserInput As SearchInput
Public ReadOnly Property UserInput() As SearchInput
Get
Return mUserInput
End Get
End Property
Public Sub New(ByVal UserInput As SearchInput)
mUserInput = UserInput
End Sub
End Class
Private Overloads Sub DataPortal_Fetch(ByVal criteria As FilteredCriteria)
Fetch(criteria.UserInput)
End Sub
End Class
Sorry about the formatting of the prototype, I don't know why it turned out that way
Yes, your prototype is headed in the right direction.
Then all you need is SearchInput, which would inherit from
BusinessBase, but would only include the Business Methods, Business Rules
and Factory Methods regions. The NewInput() factory would be:
Public Shared Function NewInput() As SearchInput
Return New SearchInput
End Function
So there’d be no data portal interaction in this class at
all.
Rocky
Rocky,
Thanks so much for your guiding me to the right solution, helping review my prototype and giving valuable advices. Sure I will remember to only include the Business Methods, Business Rules and Factory Methods regions in the SearchInput BO.
This is my first app using the csla framework. With all the kind assistance from this wonderful community, I'm more confident than ever to use the framework. I also bought and read your book on it, I enjoyed reading the theroy chapters as well as the example chapters. Excellent book, in my mind.
Thanks again for all your time.
You got it.
That is the exact technique I use for my Search screens.
Joe
Joe,
Do you bind your search screen to the BO at design time or run time? Just curious.
Copyright (c) Marimer LLC