Recommendations on how to implement a validation class? - oop

I am implementing a validation class in classic ASP. How should the validation class interface with my other classes?
My current setup:
The User class's set methods call the appropriate validation method in the validation class. Any errors that occur are stored in User.mError. For example, here's my set method for the Email member variable in ASP Classic:
Class User
Property Let Email(EmailInput)
If (myValidation.isEmail(EmailInput)) then
mEmail = EmailInput
Else
mError = "Invalid Email Address format."
End If
I don't like how I'm going to need an error member variable for every object that calls my validation class. Suggestions on a better setup?
Any suggestions for a validation architecture I should review as a benchmark?

You should try the validation concept used in ajaxed (which is an AJAX library for classic ASP - www.webdevbros.net/ajaxed/). Unfortunately the validator will be officialy released in version 2.0 but its already available in SVN - you could easily use it without the whole library (standalone)
Ajaxed has a class called validator which you can use to validate your business objects. It requires the creation of an isValid() method which takes a Validator as an argument and returns if the instance is valid or not. The isValid() method is called before saving the instance. It performs all validations and fills the given validator if anything is invalid.
Example:
class User
public firstname
public lastname
'validates the user instance
'- call before save()
public function isValid(byRef v)
isValid = true
if len(firstname) < 5 then
v.add "firstname", "Firstname must be at least 5 chars long."
isValid = false
end if
if len(lastname) < 5 then
v.add "lastname", "Lastname must be at least 5 chars long."
isValid = false
end if
end function
public sub save()
'do some DB stuff
end sub
end class
'usage scenario 1 (simple - we just know if valid or not)
set u = new User
if u.isValid(new Validator) then
u.save()
else
response.write("User is invalid. some error happend")
end if
'usage scenario 2 (detailed - we have an error summary)
set u = new User
u.firstname = "Michal"
set v = new Validator
if u.isValid(v) then
u.save()
else
'the validator offers a helper to create a validation summary
response.write(v.getErrorSummary("<div><ul>", "<ul/></div>", "<li>", "</li>"))
end if
'usage scenario 3 (we can even validator more users in one go)
set u1 = new User
set u2 = new User
set v = new Validator
u1.isValid(v)
u2.isValid(v)
if v then
u1.save()
u2.save()
else
response.write("something is invalid")
end if
I am using this aproach for years already and its very flexible. You can use the Validator class as standalone but I would recommend you use the ajaxed library as a whole. It lets you develop ASP more easier.

I would suggest looking at Validator related classes provided by .net framework.
In your case, you can have a Validator Class (EmailValidator to be specific), which could have a method named Validate which takes a string, returns a boolean
You could also pass ErrorMessage as one of the parameters of the Validate function
e.g.
Psuedo Code.
class EmailValidator
...
function Validate(byval EmailAddress as string, optional byval Result as string) as boolean)
..
if (condition success)
result = success
elseif (emailafddress doesnt have #)
result = "invalid email address. missing #"
endif
end function
end class
You can take error message out, if you want to have control over it.
I invite fellow SO guys to suggest any shortcomings in this.

Spring has its own validator pattern for validating sophisticated objects and returning multiple errors. It's detailed here.

I have written my own Validator class a few different ways. Validation in nature doesn't necessarily require an instantiated object, so I created a class with static methods to do validation. I have used one validator method where you have to pass a type in (e.g. Email, First Name, website...), or multiple methods each for the given types. In the end, there is really only one algorithm that I needed, so I went with the one method approach. Essentially, there are class properties to hold your validation regular expressions for each type, as well as an associated error message for the given type. It all equates to a class similar to the one below:
class Validation
{
// define the properties for dealing with different type validations
public static $firstNamePattern = '/[-a-zA-Z0-9._ ]{2,}/';
public static $lastNamePattern = '/[-a-zA-Z0-9._ ]{2,}/';
// ... more fields
public static function validateText($type, $text, $fieldName)
{
$pattern = $type."Pattern";
if ($this->$pattern != '')
{
// perfom the validation
// ...
return true; // or false
}
}
// other validation methods below
// ...
}
Then you can call that method from anywhere you need to (e.g. while validating form input).
if (Validation->validateText('firstName', $formFirstName, 'First Name'))
{
// validation passed
}
else
{
// validation failed
}
I apologize the above is written in PHP and the question was about ASP, but you get my drift.

Related

What to call an object that acts like an enter-only-once gate?

What would you call a stateful function/object x() -> bool with the following behavior: on the first call it returns TRUE, on all consecutive calls it returns FALSE. Maybe there is a pattern name already for such functionality?
The closest concept is the read-once object pattern from the Secure by Design book. Look at the paragraph below describing the object that allows to request the password only once.
A read-once object is, as the name implies, an object designed to be read once. This object
usually represents a value or concept in your domain that’s considered to be sensitive
(for example, passport numbers, credit card numbers, or passwords). The main purpose
of the read-once object is to facilitate detection of unintentional use of the data
it encapsulates.
public final class SensitiveValue {
private transient final AtomicReference<String> value;
public SensitiveValue(final String value) {
validate(value);
this.value = new AtomicReference<>(value);
}
public String value() {
return notNull(value.getAndSet(null),
"Sensitive value has already been consumed");
}
#Override
public String toString() {
return "SensitiveValue{value=*****}";
}
}
I don't know the full context of your problem but the book suggests to use the read-once object pattern in favor of security perspective. #jaco0646 also pointed out in the comments that the concept is similar to the circuit breaker pattern. Though it doesn't force for the object to always return the same value on consecutive calls. Instead, it temporary makes to obtain the stub value to give the external service some time to recover.

how to hide field during serialization (but not deserialization)

In our project (springMVC) Rest API project I wish to only use ONE model for both request and response (to avoid having to add tons of code to copy field from object to object)
I'd like to use Swagger to handle all the doc, but I'm running into a little problem. For example let say I have a model User
public class User {
private Long id;
private String username;
private String password;
}
And a simple controller
public void createUser(#RequestBody User user)...
public User getUser(Long id) ..
Now I would like swagger to hide the property password on deserialization but not serialization (so having it display for the Input but the output)
and the opposite for the Id field.
I have tried using #JsonIgnore coupled with #JsonProperty but on the swagager-ui it either displays everything or hides everything. I cannot manage to it work.
Could someone indicate me what is the best way of archiving my goal ? Is it possible to use a single model for request and response while using swagger? In case it is not possible to use #JsonIgnore, is there a way to archive this differently ?
Swagger doesn't want you to have different input/output models with the same name. You should simply create an interface and attach that to the input, and for the output extend that interface or add an implementation with the additional field. For example, please see here for modeling tips:
https://swaggerhub.com/api/swagger-tutorials/modeling-samples/1.0.0
Your exact use case is one of them. The solution posted in the above link is here:
definitions:
User:
description: this is a user that would be passed into the system
properties:
username:
type: string
UserResponse:
allOf:
- $ref: '#/definitions/User'
- type: object
required:
- id
properties:
id:
type: string
format: uuid
readOnly: true
where User is the input object, and UserResponse is the output object, with the additional id field.
Add #JsonIgnore with getter of the field and #JsonProperty with the setter or with the field . As Due to use of immutable code or final fields sometime setter doesn't work.
example :
public class Student {
private Float name;
private String rollnum;
private String section;
#JsonProperty
private Boolean passOrFailed;
#JsonIgnore
public Boolean getpassOrFailed {
return active;
}
}
Remember to use both else else it will lead to removing element in deserialization

CWebUser and CUserIdentity

I'm building an authentication module for my application and I don't quite understand the relation between CWebUser and CUserIdentity.
To set the user id to Yii::app()->user->id I have to do that in my UserIdentity class and create a method:
public function getId() {
return $this->_id;
}
But to set isAdmin to Yii::app()->user->isAdmin I have to create a method in my WebUser class:
function getIsAdmin() {
$user = $this->loadUser(Yii::app()->user->id);
return intval($user->user_level_id) == AccountModule::USER_LEVEL_ADMIN;
}
Why can't I just create the methods the UserIdentity class? What is the division of labour here?
The UserIdentity (UI) class is like an ID card, where as the WebUser class is the actual person plus everything you know about them.
The UI class gives you authentication via database, webservices, textfile, whatever. It lets you know what the key attributes are and allows you to manipulate them. The user however can give you more information about what they're allowed to do, there names, granular permissions and such.
OK, end metaphor
The UI class holds the key information, so when asking for the users ID it will refer to the User Identity class to get the Identifier for the user.
Anything that isn't related to identifying or authenticating a user is in the WebUser class
Clear it up at all?
Your example
You gave the getId function as an example, but that can be created on WebUser to override the default, which is to pull from the state.
So not sure what you mean here.
I like how the accepted answer used real life examples to make it easier to understand. However, I also like how Chris explained it here with example.
User information is stored in an instance of the CWebUser class and
this is created on application initialisation (ie: when the User first
connects with the website), irrespective of whether the user is logged
in or not. By default, the user is set to “ Guest”. Authentication is
managed by a class called CUserIdentity and this class checks that the
user is known and a valid user. How this validation occurs will depend
on your application, perhaps against a database, or login with
facebook, or against an ldap server etc...
And what is the benefit of using all those classes? I can do everything just by User model. If I set scenario "login", password will be checked during validation. If validation is OK, I can set to session my own variable like this:
$model = new User("login");
$model->attributes = $_POST["User"];
if ($model->validate())
{
Yii::app()->session["currentUser"] = $model;
}
else
{
// .. show error
unset(Yii::app()->session["currentUser"]);
}
In User model I have then static methods to check this variable
public static function isGuest()
{
return isset(Yii::app()->session["currentUser"]);
}
public static function getCurrent()
{
return Yii::app()->session["currentUser"];
}
And I can call it very shortly:
User::isGuest();
$model = User::getCurrent();
// instead of writing this:
Yii::app()->user->isGuest;
So why should I use so complicated hierarchy of classes that is suggested by Yii? I never understood it.

How do I make a custom class available to client through a web service

I have a simple web service (asmx)built in net framework 4.0 that has multiple custom classes defined. I would like to know how to make these classes available to the client. one of the classes would be returned from a method but the others are used to pass information to the web service so the client needs to know what is included in the class. for instance
Public Class clsAddress
Public AddressType As TypeAddress
Public Location As TypeLocation
Public Line1 As String
Public Line2 As String
Public City As String
Public State As String
Public ZipCode As String
Public ZipPlus4 As String
End Class
So the client would do something like this to send the info to the webservice:
Dim tempAddressInfo As New clsAddress
tempAddressInfo.AddressType = cboAddressType.SelectedIndex 'TypeAddress.current
tempAddressInfo.Location = cboLocation.SelectedIndex 'TypeLocation.USA
tempAddressInfo.Line1 = txtAddress1.Text
tempAddressInfo.Line2 = txtAddress2.Text
tempAddressInfo.City = txtCity.Text
tempAddressInfo.State = txtState.Text
tempAddressInfo.ZipCode = txtZipCode.Text
tempAddressInfo.ZipPlus4 = txtZipPlus4.Text
mclsIdVerify.pAddressInfo = tempAddressInfo
I saw something about returning a custom class using the XMLInclude attribute in a method that returns the class. what needs to be completed so the custom classes can be sent and received by the client.
TIA
I'd normally leave a question like this to someone with more knowledge but as no one has attemped to give you an answer I'll give it a shot.
I think to be able to convert your class into an object state that can be stored or transfered across a network it needs to be serealizable. This allows it to be reconstructed at the other end.
Try putting _ above your class definition.
Even if this doesnt help hopefully it gives your something to look into.

Dependency Injection with Entity Framework 5 Database First. Getting Started?

I am looking at creating a VB.NET 11 WPF MVVM application using Entity Framework 5 and Database First (Connecting to SQL Server 2008 R2).
I have chosen Database First, as I am migrating an existing solution to WPF MVVM, where the database already exists of course.
I'd like to begin using Dependency Injection so I can Unit Test as much of my code as possible.
I don't seem to be able to find a clear and concise walk-through of how to go about using Dependency Injection with EF DB-First, and in particular with vb.net. Although even a C# example would be fine I'm sure.
What I'd really like is a simple step by step guide explaining how to setup the solution, how to setup each part ready for Dependency Injection etc, but these seem hard to come by.
So far, I've created the Solution and it's Projects, as follows;
DBAccess - This houses nothing but my .edmx file, and a small mod to be able to supply the ConnectionString to the constructor.
DBControl - This houses the various classes which I use to provide a layer between my EDMX and my ViewModels. Specifically, I'm filling Complex Types (Which I have created using the designer) here for displaying "Friendlier" data via the UI, as well as converting these "Friendly" Complex Types to the mapped entities for saving / Updating. I have one class per table in my database. Each with two "FetchFriendlyRecords" methods (One accepts Filters) and an "AddUpdateFriendlyRecord" method. I have created an Interface for each class. Each class accepts a DbContext in it's constructor, and I'm simply passing my DBContext from the DBAccess Project.
MainUI - This houses my MVVM layers, and references each class in the DBControl Project in order to provide DataBinding etc.
I've seen suggested that, instead of spending time writing a complex solution to be able to unit test with EF, it's simpler to create a firm mock database with test data populated, and simply point the code at the mock database, rather than the live one. However, I'd prefer to be able to create an in memory solution that would run without any need to hit SQL Server at all.
Any help would be great, including telling me if I'm going about this all wrong!!
Update:
I have taken the solution provided by Paul Kirby below, and created a "Sort of" Repository Pattern I believe.
I created an interface;
Public Interface IFriendlyRepository(Of T)
ReadOnly Property FriendlyRecords As ObservableCollection(Of T)
Function GetFilteredFriendlyRecords(predicates As List(of Func(Of T, Boolean))) As ObservableCollection(Of T)
Function AddEditFriendlyRecord(ByVal RecordToSave As T) As EntityException
Sub SaveData()
End Interface
I then implemented this interface on a class by class basis;
Namespace Repositories
Public Class clsCurrenciesRepository
Implements Interfaces.IFriendlyRepository(Of CriticalPathDB.FriendlyCurrencies)
Private _DBContext As CriticalPathEntities 'The Data Context
Public Sub New(ByVal Context As DbContext)
_DBContext = Context
End Sub
Public ReadOnly Property FriendlyRecords As ObservableCollection(Of FriendlyCurrencies) Implements Interfaces.IFriendlyRepository(Of CriticalPathDB.FriendlyCurrencies).FriendlyRecords
Get
' We need to convert the results of a Linq to SQL stored procedure to a list,
' otherwise we get an error stating that the query cannot be enumerated twice!
Dim Query = (From Currencies In _DBContext.Currencies.ToList
Group Join CreationUsers In _DBContext.Users.ToList
On Currencies.CreationUserCode Equals CreationUsers.User_Code Into JoinedCreationUsers = Group
From CreationUsers In JoinedCreationUsers.DefaultIfEmpty
Group Join UpdateUsers In _DBContext.Users.ToList
On Currencies.LastUpdateUserCode Equals UpdateUsers.User_Code Into JoinedUpdateUsers = Group
From UpdateUsers In JoinedUpdateUsers.DefaultIfEmpty
Where (Currencies.Deleted = False Or Currencies.Deleted Is Nothing)
Order By Currencies.NAME
Select New FriendlyCurrencies With {.Currency_Code = Currencies.Currency_Code,
.NAME = Currencies.NAME,
.Rate = Currencies.Rate,
.CreatedBy = If(Currencies.CreationUserCode Is Nothing, "", CreationUsers.First_Name & " " & CreationUsers.Last_Name),
.CreationDate = Currencies.CreationDate,
.CreationUserCode = Currencies.CreationUserCode,
.Deleted = Currencies.Deleted,
.LastUpdateDate = Currencies.LastUpdateDate,
.LastUpdatedBy = If(Currencies.LastUpdateUserCode Is Nothing, "", UpdateUsers.First_Name & " " & UpdateUsers.Last_Name),
.LastUpdateUserCode = Currencies.LastUpdateUserCode}).ToList
Return New ObservableCollection(Of FriendlyCurrencies)(Query)
End Get
End Property
Public Function GetFilteredFriendlyRecords(predicates As List(of Func(Of FriendlyCurrencies, Boolean))) As ObservableCollection(Of FriendlyCurrencies) Implements Interfaces.IFriendlyRepository(Of CriticalPathDB.FriendlyCurrencies).GetFilteredFriendlyRecords
Dim ReturnQuery = FriendlyRecords.ToList
For Each Predicate As Func(Of FriendlyCurrencies, Boolean) In predicates
If Predicate IsNot Nothing Then
ReturnQuery = ReturnQuery.Where(Predicate).ToList
End If
Next
Return New ObservableCollection(Of FriendlyCurrencies)(ReturnQuery)
End Function
Public Function AddEditFriendlyRecord(ByVal RecordToSave As FriendlyCurrencies) As EntityException Implements Interfaces.IFriendlyRepository(Of CriticalPathDB.FriendlyCurrencies).AddEditFriendlyRecord
Dim dbCurrency As New Currency
' Check if this Staff Member Exists
Dim query = From c In _DBContext.Currencies
Where c.Currency_Code = RecordToSave.Currency_Code
Select c
' If Asset exists, then edit.
If query.Count > 0 Then
dbCurrency = query.FirstOrDefault
Else
'Do Nothing
End If
dbCurrency.Currency_Code = RecordToSave.Currency_Code
dbCurrency.NAME = RecordToSave.NAME
dbCurrency.CreationDate = RecordToSave.CreationDate
dbCurrency.CreationUserCode = RecordToSave.CreationUserCode
dbCurrency.LastUpdateDate = RecordToSave.LastUpdateDate
dbCurrency.LastUpdateUserCode = RecordToSave.LastUpdateUserCode
dbCurrency.Deleted = RecordToSave.Deleted
' Save Asset Object to Database
If query.Count > 0 Then
' If Asset exists, then edit.
Try
'_dbContext.SaveChanges 'We could save here but it's generally bad practice
Catch ex As EntityException
Return ex
End Try
Else
Try
_DBContext.Currencies.Add(dbCurrency)
'_dbContext.SaveChanges 'We could save here but it's generally bad practice
Catch ex As EntityException
Return ex
End Try
End If
Return Nothing
End Function
Public Sub SaveData() Implements Interfaces.IFriendlyRepository(Of CriticalPathDB.FriendlyCurrencies).SaveData
_DBContext.SaveChanges()
End Sub
End Class
End Namespace
I used constructor injection to insert the dbContext into the class.
I had hoped to be able to mock up a fake dbContext using my existing context and the "Effort" Unit Testing Tool.
However, I don't seem to be able to get this to work.
In the interim, in my Unit Test Project, I am dropping (If it already exists) and creating an empty test database, with the SQLCMD command, using the same schema as my live database.
I then create a dbContext referencing the Test Database, populate it with test data, and test against this.
As a note, I will be refactoring my "Add/Edit" method to work with an actual base Entity, rather than my "Friendly" complex version, this was the simplest method at the time.
If you're working DB-first, here's what I would suggest.
Open your .edmx file, right click on any blank space and choose "Add Code Generation Item"
In the "Online Templates" area, search for "EF 5.x DbContext Generator for VB".
Give the .tt file a name, hit add. This will change the way your .edmx file generates the backing code so that your entities are all POCO, which simplifies testing overall by keeping your main logic disconnected from EF.
After you've got that done, you probably want to look into something like the Unit of Work pattern. Here's a quick code example, I'll explain it after.
public interface IUnitOfWork
{
IDbSet<Location> Locations { get; }
void Commit();
}
public class EFUnitOfWork : IUnitOfWork
{
private readonly YourGeneratedDbContext _context;
public EFUnitOfWork(string connectionString)
{
_context = new YourGeneratedDbContext();
}
public IDbSet<Location> Locations
{
get { return _context.Locations; }
}
public void Commit()
{
_context.SaveChanges();
}
}
This is a basic unit of work that exposes some list of Locations as an example (sorry that it's in C# but I don't know VB well).
Notice that it is exposing IDbSet objects - this is where the magic comes in. If in your DBAccess project, you use this unit of work or a repository pattern to hide EF, and because it implements an interface and is returning IDbSet objects, anywhere that needs your data can have this IUnitOfWork constructor injected with DI, and replaced with a mocked version that returns mock IDbSet objects (they're just IQueryables in the end) when you need to unit test.
You may find that with the POCO generation in that new template, you can even do away with a lot of the work you're doing in your DBControl project.
Anyway that's just some basic stuff in terms of positioning your project for optimal unit testing and DI.