Skip to content

Commit 4f459d1

Browse files
committed
Update README for v1
1 parent b2ad896 commit 4f459d1

1 file changed

Lines changed: 122 additions & 3 deletions

File tree

README.md

Lines changed: 122 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,128 @@
11
# CSF Validation
2-
Validation library, currently undergoing a rewrite from scratch.
2+
CSF.Validation is a business rule validation framework.
3+
It is intended for use within the business logic layer of your application.
34

4-
The previous version is not particularly fit for use, and this rewrite is not yet ready for use.
5+
## How this differs from other frameworks
6+
Many validation frameworks (such as [ASP.NET validation controls] or [.NET validation attributes]) are intended for validation which lies close to the user interface.
7+
This is evident in their design, for example the validation failure messages are defined along with the validation rule itself.
8+
The human-readable failure message is a presentation/UI concern and not directly related to the the pass/fail of the rule logic.
59

6-
### Continuous integration builds
10+
[ASP.NET validation controls]: https://msdn.microsoft.com/en-us/library/debza5t0.aspx
11+
[.NET validation attributes]: https://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.validationattribute(v=vs.110).aspx
12+
13+
CSF.Validation separates concerns appropriately so that each aspect of the validation process may be controlled separately.
14+
If you wanted a simple validator which you will (architecturally speaking) keep close to your UI, then this framework is probably not for you.
15+
16+
If you want a shared validation framework which will live in your business logic layer, validating requests which come from a wide variety of other layers then this might be what you are looking for.
17+
18+
## Usage
19+
The process of validating an object is:
20+
21+
1. Create a validation manifest, which lists the rules which are desired, along with their configurations
22+
2. Use a validator factory to create a validator from that manifest
23+
3. Use the validator to validate your object
24+
25+
At the first stage, there is a static type named `ManifestBuilder` which can help you with the creation of a validation manifest.
26+
It provides a fluent interface to add and configure rules in the manifest.
27+
28+
## Example
29+
Here is an example of usage, including the creation of your own custom validation rule:
30+
31+
```csharp
32+
// A simple object model which we are going to validate
33+
34+
public interface IDessert
35+
{
36+
string Name { get; }
37+
decimal UnitPrice { get; }
38+
}
39+
40+
public interface IPurchaseDessertRequest
41+
{
42+
IDessert DessertToPurchase { get; }
43+
decimal MoneyInWallet { get; }
44+
int DesiredQuantity { get;
45+
}
46+
47+
// A custom validator type
48+
49+
// using CSF.Validation.Rules;
50+
public class CanAffordDessertRule : Rule<IPurchaseDessertRequest>
51+
{
52+
protected override RuleOutcome GetOutcome(IPurchaseDessertRequest request)
53+
{
54+
if(request == null)
55+
return Success;
56+
57+
var totalCost = request.DessertToPurchase.UnitPrice * request.DesiredQuantity;
58+
if(totalCost > request.MoneyInWallet)
59+
return Failure;
60+
61+
return Success;
62+
}
63+
}
64+
65+
// Code to construct the validator for this
66+
67+
// using CSF.Validation;
68+
// using CSF.Validation.Manifest;
69+
// using CSF.Validation.Manifest.Fluent;
70+
// using CSF.Validation.Manifest.StockRules;
71+
public IValidator CreatePurchaseDessertRequestValidator()
72+
{
73+
var builder = ManifestBuilder.Create<IPurchaseDessertRequest>();
74+
75+
builder.AddRule<NotNullRule>();
76+
77+
builder.AddMemberRule<NotNullValueRule>(x => x.DessertToPurchase, c => {
78+
c.AddDependency<NotNullRule,IPurchaseDessertRequest>();
79+
});
80+
81+
builder.AddMemberRule<NumericRangeValueRule>(x => x.DesiredQuantity, c => {
82+
c.Configure(r => {
83+
r.Min = 1;
84+
});
85+
c.AddDependency<NotNullRule,IPurchaseDessertRequest>();
86+
});
87+
88+
builder.AddMemberRule<CanAffordDessertRule>(c => {
89+
c.AddDependency<NotNullValueRule,IPurchaseDessertRequest>(x => x.DessertToPurchase);
90+
c.AddDependency<NumericRangeValueRule,IPurchaseDessertRequest>(x => x.DesiredQuantity);
91+
});
92+
93+
var factory = new ValidatorFactory();
94+
return factory.GetValidator(builder.GetManifest());
95+
}
96+
97+
// We get our validation result
98+
99+
var validator = CreatePurchaseDessertRequestValidator();
100+
var request = GetPurchaseDessertRequest();
101+
var result = validator.Validate(request);
102+
```
103+
104+
This example creates a validator with four validation rules:
105+
106+
* A not-null rule ensures that the request is not null
107+
* A not-null member rule ensures that the **DessertToPurchase** property is not null
108+
* A numeric range rule ensures that the **DesiredQuantity** property is at least 1
109+
* A custom rule ensures that the buyer can afford their desserts
110+
111+
Note the use of `.Configure()` in the numeric range rule.
112+
When building a validation manifest you may configure parameters in each individual rule via property setters on that rule.
113+
114+
Additionally, note that most of the rules have dependencies.
115+
The way dependencies work is that a rule which carries a dependency will not be executed (it will be marked as *skipped due to dependency failure* in the results) if any of the rules it depends upon have failed.
116+
In the example above, there is no point executing any of the property rules if the request itself is `null`.
117+
There is also no way to get a meaningful result from the `CanAffordDessertRule` if either the dessert is `null` or if the desired quantity is less than one.
118+
119+
Dependencies will automatically form chains; if a dependency rule is skipped due to a dependency failure of its own then any rules depending upon it will also be skipped.
120+
121+
A validation result contains a list of every validation rule in the manifest and the outcome of every single rule.
122+
Rules which have an outcome of `Success` or `IntentionallySkipped` (used in advanced scenarios) should be considered OK to allow validation to pass.
123+
Any other outcome indicates a validation failure.
124+
125+
## Build status
7126
CI builds are configured via both Travis (for build & test on Linux/Mono) and AppVeyor (Windows/.NET).
8127
Below are links to the most recent build statuses for these two CI platforms.
9128

0 commit comments

Comments
 (0)