39 people following this project (follow)

Project Description
SpecExpress is a fluent validation framework and container for .Net that makes it easier to write validation rules and validate your objects. SpecExpress also offers integration with ASP.NET WebForms, eliminating duplication of your validation rules.

Source Code moved to GitHub!

We may explore mirroring it here in the future, but for now consider the Source Code stored here on CodePlex an archive.

SpecExpress is now available to be referenced in your project through NuGet packages.

News and update information can be found at:

http://specexpress.blogspot.com

Features

  • The SpecExpress DSL provides developers with a Fluent Interface for quickly composing rules that are also easy to read. See a Sample
  • Generates error message from your validation rules, but allows for easy overriding and customization of individual messages. Support for localization of error messages.
  • Validation Catalog allows:
    • Auto discovery of specifications means the developer isn't required to resolve which validation rules to use
    • Programatically add or change validation rules at runtime
    • Validation Contexts
  • Support for rich, complex object types and graphs
  • Built with extension and customization in mind
  • Easy to integrate into your existing code because there are no Base Classes or Attributes to inject into your code
  • ASP.NET WebForms support
  • ASP.NET MVC support
  • Silverlight support
  • A rich set of Validators

Approach

SpecExpress takes a different approach than most other Validation Frameworks, such as Validation Application Block. SpecExpress doesn't use Attributes to decorate properties and embed all the metadata required for the rule. Instead, it it uses a separate class, called a Specification, which contains a set a rules for all the properties for a type. This allows for much easier reading, separation of concerns, and much better support for state based validation.

Example

public class AddressSpecification : Validates<Address>
{
    public AddressSpecification()
    {	
        Check(a => a.Street1).Required().And.IsAlpha().And.MaxLength(255);
	Check(a => a.Street2).Optional().And.IsAlpha().And.MaxLength(255);
	Check(a => a.City).Required().And.IsAlpha().And.MaxLength(50);

	Check(a => a.State)
            .If(a => a.Country == "US").Required()
		.And.IsAlpha()
		.And.LengthEqualTo(2);
		.And.IsInSet(StateRepository.GetStates());

	Check(a => a.Country).Optional().And.IsAlpha();

	Check(a => a.ZipCode)
	    .If(a => a.Country == "US").Required()
		.And.LengthEqualTo(5)
		.And.Not.EqualTo("00000");

	Check(a => a.ZipPlusFour)
	   .If(a => a.ZipCode.Any()).Required()
		.And.LengthEqualTo(4)
		.And.IsNumeric();	
    }
}

Getting Started

Check out the Quick Start or Developers Guide.

Requirements

SpecExpress requires Microsoft .Net 4.0.

Additional Resources

News

 SpecExpress News Feed 
Wednesday, January 11, 2012  |  From SpecExpress


A powerful feature of SpecExpress is it's ability to automatically generate user readable error messages for broken rules, and gather all of them up to display. In order to use this functionality, you need to create a Specification with the rules defined, add that specification to the ValidationCatalog, call Validate, and handle the ValidationNotification that is returned. But, sometimes specifications can be overkill for your needs. You might not need the reuse of a specification, or you might have rules that only need to be applied in a specific context.

We've recently add a new feature called Inline Specifications to SpecExpress that allows you to use SpecExpress to create your validation rules and messages, and not need the ValidationCatalog or just let you throw an exception. Here's what they look like in action.

Assert Inline Specification
public void DoWork(Request request)
{


//Before we do our work, validate the request, and throw an exception if invalid
Specification.Assert(sp => 
{
sp.Check(s => request.Field1).Required().EqualTo("Yellow"));
sp.Check(s => request.Field2).Required().EqualTo("Blue"));
})
}




Will create a ValidationNotificationException with all the broken rules.

Validate Inline Specification
public void DoWork(Request request)
{

//Before we do our work, validate the request
var validationNotification = Specification.Validate(sp => 
{
sp.Check(s => request.Field1).Required().EqualTo("Premium"));
sp.Check(s => request.Field2).Required().EqualTo("Blue"));
})

if (!validationNotification.IsValid)
{
//Log error and state then precede
}
}




Monday, September 19, 2011  |  From SpecExpress

We recently received a post from Karl:

I didn't see an example or documentation for using SpecExpress along with IDataErrorInfo.  Is it possible?
Thank you, SpecExpress looks great,
Karl

Well Thanks Karl!  We think SpecExpress looks great to!  Using IDataErrorInfo with SpecExpress is VERY possible.  A matter of fact it makes implementing IDataErrorInfo in your model classes extremely simple.

For those that are unfamiliar with IDataErrorInfo, IDataErrorInfo is an interface that a UI framework such as WPF, Silverlight, and MVC can bind to when data validation errors occur.  The interface exposes two member properties:

  • Error – gets an error message indicating what is wrong with the object
  • Item – an index based property that gets an error message for a given property given the property name provided as the index

Implementing these two interfaces is as simple as this:

using System.ComponentModel;
using SpecExpress;

namespace MvcApplication5.Models
{
public class Contact : IDataErrorInfo
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }

#region IDataErrorInfo
public string this[string columnName]
{
get
{
return ValidationCatalog.ValidateProperty(this, columnName).ToString();
}
}

public string Error
{
get { return ValidationCatalog.Validate(this).ToString(); }
}

#endregion
}
}



You may even want to consider implementing the interface in an abstract base class that all your model classes inherit from!  The beauty of this code is the simplification you get in defining the model class.  The aspect of business rules delegated to SpecExpress’ ValidationCatalog through a single line of code for each property!


Of course, using MVC, the IDataErrorInfo interface is called on the server side each time the data is posted to the controller through a post back.  Sometimes, especially for lengthy forms, this may not be the optimum user experience.  With SpecExpress, we have written an MVC Integration library that leverages the JQuery Validation library for client side validation.  Through the MVC Integration, the appropriate client side validation is automatically called based upon the validation rules expressed and registered in the ValidationCatalog.  See the documentation and sample code in the source code for more specifics on this integration.

Monday, August 08, 2011  |  From SpecExpress

You can only discuss functionality from the aspect of the impact the functionality has on a given consumer.  Given the fact that we are discussing a “framework”, the consumer that is going to be most impacted is the developer consuming the framework.  After all, a developer can deliver the same user experience with or without the use of the framework.  A good framework should allow the developer to deliver this user experience with the least amount of effort while increasing the maintainability.  So with that in mind lets discuss some functionality I would expect a Validation Framework to deliver.

Fluent Interface

Dictionary.com defines fluent as “ able to speak or write smoothly, easily, or readily”.  Eric Evans and Martin Fowler first coined the term “fluent interface” as it applies to an API, allowing the developer to easily and readily interact with it.  This is usually done through the use of method chaining.  By implementing a fluent interface, a Validation Framework will all a developer to easily express validation rules, leveraging intellisense along the way.

Check(c => c.FirstName).Required().MaxLength(50).IsAlpha();



Use of Expressions


Many frameworks rely on strings being passed in as parameters that indicate a property that is to be referenced or a method that is to be invoked.  The problem with doing so is that these strings often get missed when renaming a property or method.  By using expressions, represented as lambdas, we not only facilitate all the renaming, but also give the developer more flexibility to express what they wish in the lambda, and allow them to take advantage of intellisense – something lacking when defining a string.


Of course, a Validation Framework should allow me to utilize expressions when declaring the target of a rule such as when I want to declare a rule for the StartDate property of a class defining a Meeting:

Check(m => m.StartDate).Required();

However, in a lot of situations, a rule needs to reference other properties, or call other methods, or rely on some other piece of data that is declared elsewhere in application.  This is where I see a lot of Validation Frameworks fall short.  Consider a class defining a Meeting where a rule may be “StartDate must be before EndDate”.  Many frameworks require you to implement your own delegate and call it as part of a “custom” rule.  SpecExpress allows you to declare this rule as part of the standard GreaterThan or LessThan rules:

Check(m => m.StartDate).Required().LessThan(m => m.EndDate);

A matter of fact all argument based rules that are implemented by SpecExpress have an overload that takes a constant, as well as an overload taking in an expression.


Implementation of Most Common Rules


A Validation Framework is only as useful as the rules it implements out of the box.  In my opinion, this is another area where a lot of frameworks lack.  Many frameworks give you a subset and leave the rest to be implemented by you – the consuming developer. 


At last count, SpecExpress has implemented 30 rules that cover:



  • Required

  • Boolean (IsTrue, IsFalse)

  • Collections (Contains, IsEmpty, etc.)

  • DateTime (IsInFuture, IsInPast)

  • IComparable (Between, IsGreaterThan, IsLessThan, etc.)

  • String (MaxLength, MinLength, Alpha, Numeric, Matches, etc.)

  • Custom (for the rare occasion where you need it)

Combining Rules


Often times, there are relations between rules.  For instance, I may have rules for a serial number that states “The serial number must start with a ‘y’ or a ‘z’ and be 10 characters long”.  Many frameworks consider this to be a “complex rule” that must be implemented in a custom delegate, but in SpecExpress, by using the Matches and LengthEquals rules, this can be expressed through the fluent interface and not relegated to be implemented in a delegate:

Check(i => i.SerialNumber).Required()
.Group(s => s.Matches("^y.*")
.Or
.s.Matches(“^z.*”)
.And.LengthEqualTo(10));

In the above example, a Group is defined to control the precedence of the “And” and the “Or” operations.  Just like in normal C#, an “And” takes precedence over the an “Or”.


Summary


By focusing on the developer experience, SpecExpress has provided a Validation Framework not only assists the developer express the rules through Intellisense, but also reduces the amount of code that code they would need to write for what other frameworks would consider “complex” validation.  However, SpecExpress has not ignored the fact that there may be situations that were either simply overlooked, or would be better expressed through extending SpecExpress. In my next post, I will show two ways to extend and customize SpecExpress.

 SpecExpress News Feed 


Contribute

  • Localization of error messages

Last edited Mar 8 at 12:30 PM by TechnoAg, version 47